陶陶摘蘋果(升級版)P1478_巧妙模擬

如此水的題竟然讓我絞盡腦汁,我在想我是否是快退役了.
這道題我看見不少解法:貪心,揹包,桶排亂七八糟一大堆.spa

題目

題目描述
又是一年秋季時,陶陶家的蘋果樹結了 n 個果子。陶陶又跑去摘蘋果,此次他有一個 a 公分的椅子。當他手夠不着時,他會站到椅子上再試試。code

此次與 NOIp2005 普及組第一題不一樣的是:陶陶以前搬凳子,力氣只剩下 s 了。固然,每次摘蘋果時都要用必定的力氣。陶陶想知道在 s<0 以前最多能摘到多少個蘋果。排序

如今已知 nn 個蘋果到達地上的高度 x[i],椅子的高度 a,陶陶手伸直的最大長度 b,陶陶所剩的力氣 s,陶陶摘一個蘋果須要的力氣 y[i],求陶陶最多能摘到多少個蘋果。it

輸入格式
第 1 行:兩個數 蘋果數 n,力氣 s。
第 2 行:兩個數 椅子的高度 a,陶陶手伸直的最大長度 b。
第 3 行~第 3+n-1 行:每行兩個數 蘋果高度 x[i],摘這個蘋果須要的力氣 y[i]io

輸出格式
只有一個整數,表示陶陶最多能摘到的蘋果數。class

雖然拿題目來湊篇幅是有一種很不道德的行爲,可是我怕你沒作過這題,因此...嘿嘿.sort

作法

既然他讓咱們求最多能拿多少個蘋果,咱們很容易想到揹包.可是細細一想好像又不是,畢竟他的前輩但是一道大水題,那麼既然他是由前一個題目疊加而做,那麼咱們把它分開求解便可.di

咱們能夠將蘋果分爲兩類,能拿的和不能拿的.
而不能拿的蘋果又有兩類,身高不夠高而不能拿的和體力不夠多而不能拿的.
那麼咱們在一開始讀入的時候就將他們給去掉,能夠節省不少大麻煩,咱們並不用關心那些拿不了的.while

而這樣讀入就有兩種方式:co

int p, m;
int x[6000], y[6000];
for(int i = 1; i <= n; i++)
{
    讀入p和m
    if(條件符合)
        x[++cnt1] = p, y[++cnt2] = m;//存入
}

第二種則是用while讀入,

int h = a + b;
int t = n;
while(t != 0)
{
    scanf("%d%d", &x[k], &y[k]);
    t--;//讀了一個減一個
    if(x[k] > h || y[k] > s)//條件符合
        x[k] = y[k] = 0;//清空
    else
        k++;//計數器加一位
}

本人使用第二種,更推薦第一種.

第二步,咱們只須要貪心最小的y[i]就行了,畢竟耗費的體力越少摘得越多嘛~並且這是沒必要擔憂x與y的值會亂掉了,由於咱們不須要再關心x了.
將y排序一邊,體力值減掉,答案加起來.因而這道題就被咱們使用巧妙的模擬解決掉了.

代碼

#include <cstdio>
#include <algorithm>
using namespace std;
int n, s, a, b;
int k = 1;
int x[6000], y[6000];
int ans;
int main()
{
    scanf("%d%d%d%d", &n, &s, &a, &b);
    int h = a + b;
    int t = n;
    while(t != 0)
    {
        scanf("%d%d", &x[k], &y[k]);
        t--;
        if(x[k] > h || y[k] > s)
            x[k] = y[k] = 0;
        else
            k++;
    }
    k--; 
    sort(y + 1, y + 1 + k);
    for(int i = 1; i <= k; i++)
    {
        s -= y[i];
        if(s >= 0)
            ans++;
        else
            break;  
    }
    printf("%d", ans);
}
相關文章
相關標籤/搜索