题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805402305150976

    经验

    1. 输入可以从1开始 for(int i = 1; i <= n; i++)
    2. 最优路径的记录方法
    3. 第19行之所以是小于等于号,因为原来第数组首先是从大到小,倒序的时候就满足从小到大的字典序,若出现相等,那么为了保证字典序最小(因为如果后面还有方案的话一定是字典序大于当前方案的)就要选择当前的硬币
    4. 大于的情况下,之所以else没有对dp[v]修改是因为这个时候就等于自己
    1. #include<algorithm>
    2. #include<cstdio>
    3. using namespace std;
    4. const int maxn = 10010;
    5. int coin[maxn], dp[maxn], choice[maxn][maxn];
    6. bool flag[maxn];
    7. bool cmp(int a, int b){
    8. return a > b;
    9. }
    10. int main(){
    11. int n, m;
    12. scanf("%d%d", &n, &m);
    13. for(int i = 1; i <= n; i++) scanf("%d", &coin[i]);
    14. sort(coin + 1, coin + n + 1, cmp);
    15. //for(int i = 0; i < n; i++) dp[i] = 0;
    16. for(int i = 1; i <= n; i++){
    17. for(int c = m; c >= coin[i]; c--){
    18. if(dp[c] <= dp[c - coin[i]] + coin[i]){//价值等于重量
    19. dp[c] = dp[c - coin[i]] + coin[i];
    20. choice[i][c] = 1;
    21. } else choice[i][c] = 0;
    22. }
    23. }
    24. if (dp[m] != m) printf("No Solution\n");
    25. else {
    26. int num = 0, c = m;
    27. for(int k = n; k >= 0; k--){
    28. if(choice[k][c] == 1){
    29. flag[k] = true;
    30. c -= coin[k];
    31. num++;
    32. }
    33. }
    34. for(int i = n; i >= 1; i--){
    35. if(flag[i] == true){
    36. printf("%d", coin[i]);
    37. num--;
    38. if(num != 0) printf(" ");
    39. }
    40. }
    41. }
    42. return 0;
    43. }