【SSL】2128可可摘苹果
Time Limit:1000MS
Memory Limit:128000K
Description
摩尔庄园有一条小径,沿着小径有n棵苹果树,从左到右编号为1、2、3、…、n。你现在有h小时的空余时间,希望用这些时间尽可能多的摘到更多的苹果。你从苹果树1出发,向前走,有选择地在一些苹果树旁停留一定的时间用来摘苹果,最后在某一棵苹果树旁结束工作。你现在已经测出从第i到第i+1棵苹果树需要走5*Ti分钟,同时还测出在第i棵苹果树旁停留,第一个5分钟可以摘到Fi只苹果,以后的每个5分钟,所摘到的苹果数量减少Di。
Input
第一行两个数n,h 表示一共有n棵苹果树,总有有h个小时的空闲时间。
第二行共有n-1个数,含义为题目中说的Ti。
第三行共有n个数,含义为题目中说的Fi。
第四行共有n个数,含义为题目中说的Di。
Output
输出仅一行,最优方案下可以总共可以摘多少只苹果。
Sample Input
2 1
10
50 100
50 50
Sample Output
150
Hint
【数据范围】
h<=24
n<=1000
ti,fi,di<=maxint
思路
这是一道分组背包。
设f[i][j]表示前i棵树花费j时间总共可以摘多少只苹果。
f[i][j]=f[i-1][j-t[i]]
f[i][j]=max(f[i][j],f[i][j-k]+在第i棵树停留5k分钟摘到的苹果)
1<=i<=n;
1<=j<=h12
1<=k<=j
最后找最大值。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t[1010],s[1010],d[1010],f[1010][1010];
int main()
{
int i,j,k,n,h,ans=0,ds,ss;
memset(f,-0x7f,sizeof(f));
scanf("%d%d",&n,&h);
f[0][0]=0;
h*=12;
for(t[1]=0,i=2;i<=n;i++)
scanf("%d",&t[i]);
for(i=1;i<=n;i++)
scanf("%d",&d[i]);
for(i=1;i<=n;i++)
scanf("%d",&s[i]);
for(i=1;i<=n;i++)
{
for(j=h;j>=t[i];j--)
f[i][j]=f[i-1][j-t[i]];
for(j=h;j>=0;j--)
{
ds=d[i];
ss=d[i];
for(k=1;k<=j;k++)
{
f[i][j]=max(f[i][j],f[i][j-k]+ds);//状态转移方程
ss-=s[i];
ds+=ss;
}
}
for(j=0;j<=h;j++)
ans=max(ans,f[i][j]);
}
printf("%d",ans);
return 0;
}