草草草 (f(x)背包)

来源:互联网 发布:淘宝上怎么改差评 编辑:程序博客网 时间:2024/04/27 14:48

第三题  草草草(grass)

问题描述:

    有N棵小草,编号0至N-1。乐滋滋巨神不喜欢小草,所以乐滋滋要剪草,使得N棵小草的高度总和不超过H。在第0时刻,第i棵小草的高度是h[i],接下来的每个整数时刻,会依次发生如下三个步骤:

(1)每棵小草都长高了,第i棵小草长高的高度是grow[i]。

(2)乐滋滋选择其中一棵小草并把它剪平,这棵小草高度变为0。注意:这棵小草并没有死掉,它下一秒还会生长的。

(3)乐滋滋计算一下这N棵小草的高度总和,如果不超过H,则完成任务,一切结束,    否则轮到下一时刻。

你的任务是计算:最早是第几时刻,乐滋滋能完成他的任务?如果第0时刻就可以完成就输出0,如果永远不可能完成,输出-1,否则输出一个最早的完成时刻。

输入格式:

第一行,两个整数N和H。 1 ≤ N ≤ 50,0 ≤ H ≤ 1000000。

第二行,N个整数,表示h[i]。0 ≤ h[i] ≤ 100000。

第三行,N个整数,表示grow[i]。1 ≤ grow[i] ≤ 100000。

    对于20%的数据, 1 N 7。

输出格式:

  一个整数,最早完成时刻或-1。

输入输出样例:

输入样例

3  16

5  8  58

2  1  1 

2  58

5  8

2  1

 

2  0

5  8

2  1

 

7  33

5  1  6  5  8  4  7

2  1  1  1  4  3  2

输出样例

1

0

-1

5

样例解释

到了第1时刻,三棵小草的高度依次是7,9,59。如果乐滋滋把高度是59的小草剪掉,那么三棵小草高度是7+9+0=16,任务完成。

 

 

第1秒剪第2棵小草,第2秒剪第0棵小草,第3秒剪6棵小草,第4秒剪第5棵小草,第5秒剪第4棵小草。

 

本体是背包+贪心

由于值会变,需要对物品选取的先后顺序排序

毫无疑问   一棵草不可能✄两次 否则无解

另外,如果最后砍得草是已知的(对应题中N=最早时刻),那这题肯定是最后砍长得快的

进而衍生,倘若最后砍的草是确定的,先砍长得慢的

我们用w(i) 表示第i时刻的价值,显然不砍的话,它是单调递增的(grow[i]>0)

所以我们在砍长得第i慢的草时,只有长速为1~i-1 的草有可能被砍,后面的草一定不会砍的

所以它的状态可以由前(i-1)棵草 得到,有单调子结构,可以Dp背包


#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<cctype>#include<iostream>#include<functional>#include<algorithm>using namespace std;#define MAXH (1000000+10)#define MAXN (50+10)struct grass{int h,g;friend bool operator<(const grass a,const grass b){return a.g<b.g;} //先割长得慢的,后割快的     int w(const int i){return h+i*g;}}a[MAXN];int n,H,f[MAXN][MAXN];  //f[i][j]表示 到第i棵 且 取了 j 棵 bool is_ok(int m){memset(f,0,sizeof(f));for (int i=1;i<=n;i++)for (int j=1;j<=min(i,m);j++){f[i][j]=max(f[i-1][j],f[i-1][j-1]+a[i].w(j));//如果到第i次时割j稞最优值 就是0/1背包 }int ans=0;for (int i=1;i<=n;i++) ans+=a[i].w(m);if (ans-f[n][m]<=H) {cout<<m<<endl;//while (1);exit(0);}return 0;}int main(){freopen("grass.in","r",stdin);freopen("grass.out","w",stdout);scanf("%d%d",&n,&H);for (int i=1;i<=n;i++) cin>>a[i].h;for (int i=1;i<=n;i++) cin>>a[i].g;sort(a+1,a+1+n);for (int i=0;i<=n;i++) is_ok(i);cout<<"-1\n";//while (1);return 0;}






原创粉丝点击