题目链接
这道题的状态转移方程比较易于确定。dp[i][j]
表示能放前i个物品的情况下,容量为j时能放物品的数量(这道题歌曲数量对应物品数量,容量对应时间)。
技巧(收获)
-
二维dp数组可以视情况优化为一维dp数组。
-
在0-1背包问题的初始化中
背包必须装满,dp[0] = 0,其他初始化为负无穷背包可以不装满,dp全部初始化为0,有关这一点的解释。
-
在遍历时,如果是找价值最大的,从后往前遍历。
参考:https://blog.csdn.net/pegasuswang_/article/details/9131619
#include <stdio.h>
#define jinge 678int max(int a, int b) {return a > b ? a : b;
}int main() {int T, n, t;int i, j; scanf("%d", &T);int song[51] = {0};int dp[10000] = {0};int count = 1;while (T--) {scanf("%d %d", &n, &t);for (i = 1; i <= n; i++) {scanf("%d", &song[i]);}for (i = 0; i <= t; i++) { dp[i] = -1;}dp[0] = 0;int ans = 0,ans_time = 0;for (i = 1; i <= n; i++) {for (j = t-1; j >= song[i]; j--) {if(dp[j - song[i]] + 1>=dp[j]){dp[j] = dp[j - song[i]] + 1;//这里的dp[j] = dp[j - song[i]] + 1;相当于dp[i][j] = dp[i-1][j - song[i]] + 1;}}}for(j=t-1;j>0;j--)if(dp[j]>ans){ans = dp[j];ans_time = j;}for(int i=0;i<t;i++){printf("%3d ",dp[i]);}printf("Case %d: %d %d\n", count++, ans + 1, ans_time + jinge);}return 0;
}/*
2
3 100
60 70 80
3 100
30 69 70
*/