给定一个时间上限和n个cd盘,每个cd有一个播放时间,要求出不超过时间上限的情况下最多的可以播放的时间以及使用的cd。难点在于,如何保存路径。
例如输入:世界上限为5,一共有3个CD,每个CD播放时间分别:1分钟、3分钟、4分钟
输出:最多可以播放的时间是第一个CD和第三个CD,播放时间为五分钟。
分析如下:
#include
#include
#include
using namespace std;
int sum, n, cd[25], i, j, k, dp[1111], out[1111][25], outn[1111];
//outn[i] 记录达到i值时用的元素个数
//out[i][0]~out[i][outn[j]] 记录达到i值时用的元素
int main() {
while (~scanf("%d", &sum)) {
scanf("%d", &n);
memset(dp, 0, sizeof(dp));
memset(out, 0, sizeof(out));
memset(outn, 0, sizeof(outn));
dp[0] = 1;
for (i = 0; i < n; i ++)
scanf("%d", &cd[i]);
for (i = 0; i < n; i ++)
for (j = sum; j >= cd[i]; j --)
if (dp[j - cd[i]] && !dp[j]) { //存在一个或几个数字组成j-cd[i]值 !dp[j]是指去掉重复的
dp[j] = 1; //存在一个或几个数字组成j值
for (k = 0; k < outn[j - cd[i]]; k ++) { //把组成j-cd[i]值的元素,复制得到j值所在的行
out[j][outn[j]] = out[j - cd[i]][k];
outn[j]++ ;
}
out[j][outn[j]++] = cd[i]; // 最后把元素cd[i]放到最后
}
for (i = sum; i >= 0; i --) {
if (dp[i]) {
sort(out[i], out[i] + outn[i]);
for (j = 0; j < outn[i]; j ++) {
printf("%d ", out[i][j]);
}
printf("sum:%d
", i);
break;
}
}
}
return 0;
}