• pta l3-1(凑零钱)


    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805054207279104

    题意:给定n枚硬币的面值,需要支付金额m,求能否恰好支付,若能,输出最小序列,若不能输出No Solution

    思路:很容易看出这是一个完全背包问题,把每枚硬币的体积视为其面值,价值也视为其面值,则题目就转换成在背包空间为m时能否刚好装满,用dp[i][j]表示前i枚硬币装在空间为j的背包中最大价值。但题目的难点在于需要输出最小序列,我们可以这样做,输入数据之后按降序排列,然后从i=1到i=n进行dp,然后输出从i=n到i=1回溯,这样的结果自然就是序列最小的。还有一点需要注意的就是:

               if(dp[j]<=dp[j-a[i]]+a[i])               

        dp[j]=dp[j-a[i]]+a[i],b[i][j]=true;

      这里必须是‘<=',这样才能保证序列最小。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=10005;
     5 int a[maxn],dp[105],res[maxn],k,n,m;
     6 bool b[maxn][105];
     7 
     8 bool cmp(int x,int y){
     9     return x>y;
    10 }
    11 
    12 int main(){
    13     scanf("%d%d",&n,&m);
    14     for(int i=1;i<=n;++i)
    15         scanf("%d",&a[i]);
    16     sort(a+1,a+n+1,cmp);
    17     for(int i=1;i<=n;++i)
    18         for(int j=m;j>=a[i];--j)
    19             if(dp[j]<=dp[j-a[i]]+a[i])
    20                 dp[j]=dp[j-a[i]]+a[i],b[i][j]=true;
    21     if(dp[m]!=m)
    22         printf("No Solution
    ");
    23     else{
    24         int v=m,t=n;
    25         while(v){
    26             if(b[t][v]){
    27                 res[k++]=a[t];
    28                 v-=a[t];
    29             }
    30             --t;
    31         }
    32         printf("%d",res[0]);
    33         for(int i=1;i<k;++i)
    34             printf(" %d",res[i]);
    35         printf("
    ");
    36     }
    37     return 0;
    38 }
  • 相关阅读:
    单片机成长之路(51基础篇)
    linux 目录/sys 解析
    单片机成长之路(51基础篇)
    python
    单片机成长之路(51基础篇)
    单片机成长之路(51基础篇)
    dos命令大全 黑客必知的DOS命令集合
    单片机成长之路(51基础篇)
    单片机成长之路(avr基础篇)- 003 AVR单片机的BOOT区
    单片机成长之路(51基础篇)
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10609806.html
Copyright © 2020-2023  润新知