Codeforces 922E Birds (DP)

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;
}

猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/80342073
今日推荐