题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805402305150976
经验
- 输入可以从1开始
for(int i = 1; i <= n; i++) - 最优路径的记录方法
- 第19行之所以是小于等于号,因为原来第数组首先是从大到小,倒序的时候就满足从小到大的字典序,若出现相等,那么为了保证字典序最小(因为如果后面还有方案的话一定是字典序大于当前方案的)就要选择当前的硬币
- 大于的情况下,之所以else没有对
dp[v]修改是因为这个时候就等于自己
#include<algorithm>#include<cstdio>using namespace std;const int maxn = 10010;int coin[maxn], dp[maxn], choice[maxn][maxn];bool flag[maxn];bool cmp(int a, int b){return a > b;}int main(){int n, m;scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) scanf("%d", &coin[i]);sort(coin + 1, coin + n + 1, cmp);//for(int i = 0; i < n; i++) dp[i] = 0;for(int i = 1; i <= n; i++){for(int c = m; c >= coin[i]; c--){if(dp[c] <= dp[c - coin[i]] + coin[i]){//价值等于重量dp[c] = dp[c - coin[i]] + coin[i];choice[i][c] = 1;} else choice[i][c] = 0;}}if (dp[m] != m) printf("No Solution\n");else {int num = 0, c = m;for(int k = n; k >= 0; k--){if(choice[k][c] == 1){flag[k] = true;c -= coin[k];num++;}}for(int i = n; i >= 1; i--){if(flag[i] == true){printf("%d", coin[i]);num--;if(num != 0) printf(" ");}}}return 0;}
