谈到背包,大家肯定都熟悉,我就不多讲,而这题挺有意思。DP[i][j] 表示前 i 首歌在j时间内唱的最多曲目;
状态有了,那么怎么转移呢? DP[i][j] = max{DP[i - 1][j],DP[i - 1][j - t[i]] + 1};
但是此题还有时间。所以如果初始化为0的话,按照平常背包的代码,很难求出最长时间。
所以我们初始化为-1,且-1时不计算,那么这就避免了01背包的情况;
是不是觉得很像01背包的恰好装满情况。对,当然可以初始化为-无穷;
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define REP(i,N) for (int i = 0;i < (N);i++) 5 #define DWN(i,N) for (int i = (N);i >= 0;i--) 6 #define INF 0x3f3f3f3f; 7 using namespace std; 8 9 int dp[2][180 * 51 +678]; 10 int a[51]; 11 int main (){ 12 int T; 13 int kase = 0; 14 //freopen("1.txt","r",stdin); 15 cin >> T; 16 while (T--) { 17 int n,t; 18 cin >> n >> t; 19 int p = 1; 20 REP(i,2) REP(j,t) dp[i][j] = -INF; 21 dp[0][0] = 0; 22 int ans = 0; 23 REP(i,n) cin >> a[i]; 24 REP(i,n) { 25 REP(j,t) { 26 dp[p][j] = dp[p ^ 1][j]; 27 if (j >= a[i]) 28 dp[p][j] = max(dp[p ^ 1][j],dp[p ^ 1][j - a[i]] + 1); 29 ans = max(ans,dp[p][j]); 30 } 31 p ^= 1; 32 } 33 DWN(i,t - 1) { 34 if (dp[p ^ 1][i] == ans) { 35 printf("Case %d: %d %d\n", ++kase, ans + 1, i + 678); 36 break; 37 } 38 } 39 } 40 }
时间: 2024-12-19 13:39:55