陶陶摘苹果(升级版)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);
}
相关文章
相关标签/搜索