分析可知,虽然t<109,但是总曲目时间大于t,实际上t不会超过180*n+678.此问题涉及到两个目标信息,首先要求曲目数量最多,在此基础上要求所唱的时间尽量长。可以定义
状态dp[i][j]表示前i首歌曲,恰好唱的时间为j时,所唱的最长时间,于是就是裸的01背包了。
/*----UVa12563 Jin Ge Jin Qu */ #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<vector> #include<string.h> #include<math.h> #include<algorithm> #define INF 0x3f3f3f3f using namespace std; const int maxn = 50 + 10; int dp[maxn*180+678]; //dp[i][j]表示前i首歌曲,时间长度恰好为j,所唱的最多曲数,可以直接使用一维数组 int t[maxn]; int main(){ int i, j,T,iCase=1,n,m; scanf("%d", &T); while (T--){ scanf("%d%d", &n, &m); m--; //在此不能恰好唱完,因为后面还要唱一首jin Ge Jin Qu for (i = 1; i <= n; i++)scanf("%d", &t[i]); for (i = 0; i <= m; i++)dp[i] = -INF; dp[0] = 0; for (i = 1; i <= n; i++){ for (j = m;j>=t[i];j--) dp[j]=max(dp[j], dp[j - t[i]] + 1); } int ans =-INF, maxt = -INF; for (j = m; j >=0; j--) if (ans < dp[j]){ ans = dp[j];maxt = j;} printf("Case %d: %d %d ",iCase++,ans + 1, maxt + 678); } return 0; }