<题目链接>
题目大意:
你要录制时间为N的带子,给你一张CD的不同时长的轨道,求总和不大于N的录制顺序
解题分析:
01背包问题,需要注意的是如何将路径输出。
由于dp时是会不断的将前面所选物品更新的,所以我们输出路径时,应该倒序,将用过的物品减去,才能得到正确的路径。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxn = 1000 + 100; int n,m,vis[maxn][maxn]; int main(){ while (scanf("%d %d", &m, &n) != EOF){ int arr[30]; for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); int dp[maxn]; memset(dp, 0, sizeof(dp)); memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++){ for (int j = m; j >= arr[i]; j--){ dp[j] = max(dp[j], dp[j - arr[i]] + arr[i]); if (dp[j] == dp[j - arr[i]] + arr[i]) vis[i][j] = 1; //用二维的vis[][]数组标记一下路径 } } int j = m; int output[maxn]; int res = 0; for (int i=n;i>=1;i--){ if (vis[i][j]){ output[++res] = arr[i]; j -= arr[i]; } } for (int i = res; i >=1; i--) printf("%d ", output[i]); printf("sum:%d ", dp[m]); } }