最少硬币问题(最多背包问题)可以测试代码过程

最少硬币问题
Time Limit: 1000 ms Memory Limit: 65536 KiB

Problem Description
设有n种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来找钱。可以使用的各种面值的硬币个数存于数组Coins[1:n]中。
对任意钱数0≤m≤20001,设计一个用最少硬币找钱m的方法。
对于给定的1≤n≤10,硬币面值数组T和可以使用的各种面值的硬币个数数组Coins,以及钱数m,0≤m≤20001,计算找钱m的最少硬币数。
Input
输入数据第一行中只有1个整数给出n的值,第2行起每行2个数,分别是T[j]和Coins[j]。最后1行是要找的钱数m。
Output
输出数据只有一个整数,表示计算出的最少硬币数。问题无解时输出-1。
Sample Input
3
1 3
2 3
5 3
18
Sample Output
5

 **************************动态规划实现********************************
  长度为m的数组f[1...m]中存放一系列子结果,即f[i]为要凑的钱数为i时
  所需的最少硬币数,则c[m]为所求;
  当要找的钱数i(1

原博客

#include

using namespace std;

const int INF = 0x3f3f3f3f;
int main()
{
    int n, m;
    cin>>n;///n种钱币
    int t[20002]; ///面值
    int c[20002]; ///个数
    int dp[20002];///用来记录钱为i时的最少硬币数
    for(int i = 1; i <= n; i++)
        cin>>t[i]>>c[i];
    cin>>m;
    memset(dp, 0, sizeof(dp));///初始化dp
    for(int i = 1; i <= m; i++)
        dp[i] = INF;///对dp[1到m]赋值无穷,方便接下来判断是否有最优解
    for(int i = 1; i <= n; i++)      ///硬币面值的种数
    {
        for(int j = 1; j <= c[i]; j++) ///硬币的面值的个数
        {
            for(int k = m; k >= t[i]; k--)///k从大到小,k = m
            {
                ///cout<<"先K="<[k] = min(dp[k - t[i]] + 1, dp[k]);///在多个解中找最优的(最小的)
                ///cout<<"后k="<
                ///cout<
            }
            ///cout<<"JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ"<
        }
        ///cout<<"IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"<
    }
    if(dp[m] == INF)
        cout<<"-1"<<endl;
    else
        cout<<dp[m]<<endl;
    return 0;
}

//硬币问题就是一个多重背包问题
//动态迁移方程为 dp[k] = min{dp[k-t[i]]+1,dp[k]}
//就是,将第i个硬币拿出去得到的一个最少的找硬币数+1,和原硬币数相比最小的那个就是结果
//另外一种思路,可以将所有的硬币价值都放在一个数组,就变成了0-1背包问题,所需考虑的就是放不放的问题


你可能感兴趣的:(算法设计-动态规划)