UVa 12563 Jin Ge Jin Qu hao【01背包】

题意:给出t秒时间,n首歌分别的时间a[i],还给出一首长度为678的必须唱的劲歌金曲,问最多能够唱多少首歌(只要最后时间还剩余一秒,都可以将劲歌金曲唱完)

用dp[i]代表花费i时间时唱的歌的最大数量 背包容量即为给出的总时间t-1(留一秒钟唱劲歌金曲)

,每首歌的代价为a[i], 然后状态转移方程为

dp[j]=max(dp[j],dp[j-a[i]]+1);

自己写的时候,一直一直wa 后来看了lrj的代码,发现是初始化不对, 改掉初始化就对了= =

可是为什么要这样初始化呢= =

后来才明白,给初始状态赋特殊的值,是因为这个状态是不合法的,不能从这个状态开始转移 比如说如果初始值都赋为0的话,dp[99]=0,那么就是一首歌都还没有唱,就已经花费了99秒钟,

所以应该初始化为-1(-2,-3,-4-5,-6,-7-------等其他取不到的特殊值)

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring> 
 4 #include <cmath> 
 5 #include<stack>
 6 #include<vector>
 7 #include<map> 
 8 #include<set>
 9 #include<queue> 
10 #include<algorithm>  
11 #define mod=1e9+7;
12 using namespace std;
13 
14 typedef long long LL;
15 const int maxn=100005;
16 int a[maxn],dp[maxn];
17 
18 int main(){
19     int n,t,i,j,ncase,kase=0;
20     cin>>ncase;
21     while(ncase--){
22         
23         cin>>n>>t;
24         for(i=1;i<=n;i++) cin>>a[i];
25         
26         int ans=0;
27         
28         for(int i = 0; i < t; i++) dp[i] = -1;
29         dp[0] = 0;
30         
31         for(i=1;i<=n;i++){
32             for(j=t-1;j>=0;j--){
33                 if(j>=a[i]) dp[j]=max(dp[j],dp[j-a[i]]+1);
34                 
35                 ans=max(ans,dp[j]);    
36             //    printf("ans=%d
",ans);
37             //    printf("dp[%d]=%d
",j,dp[j]);            
38             }
39         }
40         
41         for(i=t-1;i>=0;i--){
42             if(dp[i]==ans){
43                 printf("Case %d: %d %d
", ++kase, ans + 1, i + 678);
44                 break;
45             }
46         }
47     }
48     return 0;    
49 }
View Code
原文地址:https://www.cnblogs.com/wuyuewoniu/p/4376037.html