思路:
1. 01背包问题,价值即容量,因此只需要考虑价值。并且要找满足条件的最小序列,因为用dp后满足的答案会覆盖先满足的答案,所以将硬币从大到小排序,那么dp状态转移之后最后获得的答案就是最小序列。
2. 要输出最小序列,需要一个数组保存dp过程满足条件的选择。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 1e4 + 10;
int n, m;
int a[N], dp[N];
bool choice[N][110]; //choice[i][j]表示选择第i个硬币并且已选择硬币总值为j
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n, greater<int>());
for(int i = 1; i <= n; i++) {
for(int j = m; j >= a[i]; j--) {
//dp[j] = max(dp[j], dp[j - a[i]]+a[i])
if(dp[j] <= dp[j - a[i]] + a[i]) { // 如果等于的话就是更小的序列
dp[j] = dp[j - a[i]] + a[i];
choice[i][j] = 1;
}
}
}
if(dp[m] == m) {
bool flag = false;
for(int i = n, j = m; i >= 1; i--) {
if(choice[i][j]) {
if(flag) cout << " ";
cout << a[i];
flag = true;
j -= a[i];
}
}
cout << endl;
} else cout << "No Solution\n";
return 0;
}