题目大意:你有一张光盘,光盘上最多能播放M分钟。现在有N首歌,给出每首歌的时间,问如何挑选,才能使光盘的利用率达到最大
解题思路:01背包+路径纪录,路径纪录时可以用类似回溯的方法
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int n, m, Sum;
int val[25], path[N];
bool vis[N];
bool cmp(const int &a, const int &b) {
return a < b;
}
void solve() {
sort(val, val + n, cmp);
memset(vis, 0, sizeof(vis));
memset(path, -1, sizeof(path));
path[0] = 0;
vis[0] = true;
for (int i = 0; i < n; i++) {
for (int j = Sum - val[i]; j >= 0; j--)
if (vis[j] && !vis[j + val[i]]) {
path[j + val[i]] = j;
vis[j + val[i]] = true;
}
}
bool flag = false;
for (int i = m; i >= 0; i--) {
if (path[i] != -1) {
if (i == 0) break;
flag = true;
int t = i;
while (1) {
printf("%d ", t - path[t]);
t = path[t];
if (!t) break;
}
printf("sum:%d\n", i);
break;
}
}
if (!flag) printf("sum:0\n");
}
int main() {
while (scanf("%d", &m) != EOF) {
scanf("%d", &n);
Sum = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &val[i]);
Sum += val[i];
}
solve();
}
return 0;
}