自己花了两个小时A出来的感觉就是不一样啊,学习DP建议大家多煎熬一点,好好思考状态是如何转移的。
不过这道题我一开始理解错题意了,不然也不会浪费这么长时间 。 一开始以为是背包问题,后来才发现要求使得唱的曲目尽量多,在此前提下尽量晚离开KTV,我恰好弄颠倒了。
这样我们就不难得出递推方程 : 因为每首曲目只能唱一遍,所以这就使递推变得有序了~ 那么我们设cnt[i][j]表示唱前i首歌中的若干,且总时间不超过j 的最大歌曲数目 。
那么cnt[i][j] = max(cnt[i-1][j],cnt[i-1][j-a[i]] + 1); 因为还要使总时间尽量长,所以当cnt[i][j] == cnt[i-1][j-a[i]] + 1 时,d[i][j] = max(d[i][j],d[i-1][j-a[i]] + a[i]);
细节参见代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 55; int T,n,t,Case = 0,d[maxn][180*maxn + 678],a[maxn],cnt[maxn][180*maxn + 678]; int main() { scanf("%d",&T); while(T--){ scanf("%d%d",&n,&t); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { for(int j=0;j<=t;j++) { cnt[i][j] = (i == 1 ? 0 : cnt[i-1][j]); d[i][j] = (i == 1 ? 0 : d[i-1][j]); if(j > a[i]) { if(cnt[i][j] < cnt[i-1][j-a[i]] + 1) { cnt[i][j] = cnt[i-1][j-a[i]] + 1; d[i][j] = d[i-1][j-a[i]] + a[i]; } else if(cnt[i][j] == cnt[i-1][j-a[i]] + 1) { d[i][j] = max(d[i][j],d[i-1][j-a[i]] + a[i]); } } } } printf("Case %d: %d %d\n",++Case,cnt[n][t]+1,d[n][t]+678); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/46840327