题目
n个硬币,面值分别为V1, V2, V3……Vn,我们要凑够m元,并且要输出字典序最小的那一个方案。
思路
https://www.kancloud.cn/kancloud/pack/70133 背包九讲第九讲有关打印方案的方法。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
const int maxm = 1e3 + 10;
int n, m;
int cost[maxn], g[maxn][maxm];
int d[maxn];
bool cmp(int a, int b) {
return a > b;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> cost[i];
sort(cost + 1, cost + n + 1, cmp); // 从大到小排序
memset(d, 0, sizeof(d));
memset(g, 0, sizeof(g));
for(int i = 1; i <= n; i++) {
for(int j = m; j >= cost[i]; j--) {
if(d[j] <= d[j - cost[i]] + cost[i]) { // 注意是 <=,为什么自己想
g[i][j] = 1;
d[j] = d[j-cost[i]] + cost[i];
}
}
}
vector<int> ans;
if(d[m] != m) {
cout << "No Solution" << endl;
return 0;
}
int i = n, vv = m;
while(i && vv) {
if(g[i][vv]==1) {
ans.push_back(cost[i]);
vv -= cost[i];
}
i--;
}
int fir = 1;
for(auto & it: ans) {
if(fir) {
cout << it;
fir = 0;
}else{
cout << " " << it;
}
}
cout << endl;
return 0;
}