codeforce 461DIV2 E题

题意

有n棵树排成一排,每个树上都有c[i]只小鸟,只有站在树下才可以召唤小鸟,在i-th树下召唤k(k<=c[i])只小鸟需要消耗cost[i]*k的法力值,但是每召唤一只小鸟可以将法力值的上限增加B,每次到下一棵树时候,法力值会恢复X(但是不会超过上线),初始时的法力值和上限都是W。

分析

emmm这个题我不会,但感觉真的棒!乍一看很像背包有没有!一开始我想dp[a][b]表示在状态(a,b)时捉到小鸟的最大值,(a,b)代表第a棵树,当前法力值为b,法力值的上限可以通过捉到的小鸟数得到,那么转移就很显然dp[a][b]=max(dp[a][b],dp[a-1][b+k*cost[a]-X]+k)其中b+k*cost[a]<=W+dp[a-1][b+k*cost[a]-X]*B;如果是这样这道题就是简单的背包了,但是注意数据范围!数组开不下!!!再回去认真审题(zhao ti jie),发现有一个提示是c[i]的和小于等于十的四次方,这是在暗示我们将它加入到状态中啊!于是我们就可以这样写dp;

dp[a][b]为在状态(a,b)时剩余的最大能量值,状态(a,b)代表在第a棵树下,已经抓到了b只小鸟。那么初始状态便为dp[0][0]=W;
状态转移为dp[a][b]=max(dp[a][b],min(dp[a-1][b-k]+X,W+(b-k)*B)- cost[a]*k);初始时可以将所有的dp数组赋值为-inf;最后i从大到小找dp[n][i],当它的值大于等于0的时候(或者不等于-INF),当前i就是答案
对了,这道题不用long long 的话会在第7组WA。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int INF=2147483600;
 7 const int maxn=1000+10;
 8 const int maxc=10000+10;
 9 long long n,W,B,X;
10 long long c[maxn],cost[maxn];
11 long long dp[maxn][maxc];
12 int main(){
13     //scanf("%d%d%d%d",&n,&W,&B,&X);
14     cin>>n>>W>>B>>X;
15     long long M=0;
16     for(int i=1;i<=n;i++){
17             cin>>c[i];
18             M+=c[i];
19     }
20     for(int i=1;i<=n;i++)scanf("%d",&cost[i]); //cin>>cost[i];
21     for(int i=0;i<=n;i++)
22         for(int j=0;j<=M;j++)
23           dp[i][j]=-INF;
24     dp[0][0]=W;
25     for(int i=1;i<=n;i++){
26         for(int j=0;j<=M;j++){
27                 for(int k=0;k<=c[i];k++)
28             if(k<=j&&min(dp[i-1][j-k]+X,W+(j-k)*B)>=cost[i]*k)
29             dp[i][j]=max(dp[i][j],min(dp[i-1][j-k]+X,W+(j-k)*B)-cost[i]*k);
30         }
31     }
32 
33     int ans=0;
34     for(int i=M;i>=0;i--){
35         if(dp[n][i]>=0){
36             ans=i;
37             break;
38         }
39     }
40     printf("%d",ans);
41 return 0;
42 }
View Code
原文地址:https://www.cnblogs.com/LQLlulu/p/8825122.html