http://codeforces.com/problemset/problem/922/E
题目大意:
有n棵树,每棵树Ci个鸟,买一个花费Costi元。最开始钱包容量和钱数都是w元,且买一个鸟钱包容量增加一个定值。现在按顺序从1号树走到n号树,每换一棵树多出来x元,最多买多少鸟?
思路:
明显的一个DP,而且题目中n的范围为1000,很明显是一个二维dp,且容易看出现在走到第i棵树可以作为DP的一维。(需要经验积累,多做题啊)。继续分析:每棵树可以买c[i]只鸟,每棵树买不同的鸟的数量关系到后面的价值,关系到后面买鸟的数量,所以容易看出,鸟的数量也是dp的一维。这样,把树当作第一位也讲的通了,每一课树有不同的c[i]值。然后会发现其实时一个背包dp.本来我是想将买的鸟的数量来作为dp后的值,但是这样的话,
看题之后发现,费用数量很大,可能有1e9,显然费用不能作为DP的一维。而影响买鸟数量的因素,除了费用就是钱包容量了。而且,当鸟的数量一定时,钱包容量是相等的!
由此,我们可以把鸟的数量当做DP的另一维,去找每个对应的DP状态的剩下的钱最多是多少。
状态转移:
dp[i][j]表示走到第i棵树下,买了j个鸟剩下的钱数最多是多少,最后只要找dp[n][j]>=0的最大的j,就是答案。
转移方程:dp[i][j]=max(dp[i-1][j-k]-k*cost[i]),k表示在当前这棵树上买的鸟数,0<=k<=Ci.
ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
ll dp[1005][10005],c[1005],cost[1005];
ll n,w,b,x;
int main(void){
cin>>n>>w>>b>>x;
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=1;i<=n;i++)cin>>cost[i];
memset(dp,-1,sizeof(dp));
dp[1][0]=w;
ll sum=0;
for(ll i=1;i<=n;i++){
for(ll j=0;j<=sum;j++){
for(ll k=0;k<=c[i];k++){
ll tmp=dp[i][j]-k*cost[i];
if(tmp<0)break;
tmp+=x;
tmp=min(tmp,w+(j+k)*b);
dp[i+1][j+k]=max(dp[i+1][j+k],tmp);
}
}
sum+=c[i];
}
for(ll i=10000;i>=0;i--){
if(dp[n+1][i]>=0){
printf("%lld\n",i);
break;
}
}
return 0;
}