动态规划---纸币组合问题

题目:假设银行里一共有n种硬币,第一种硬币的价值为V1。假设想把k元兑换成零钱,一共有多少种兑换方案。

例如,一共有1,2,5三种硬币,k = 5,则有以下兑换方案:11111,1112,122,5。共有4中兑换方案。

 动态规划问题最重要的是要找到状态转移方程!!!
用dp[i][sum]表示使用前i种硬币来组合sum这些钱有多少种兑换方案。那么

dp[i][sum] = dp[i-1][sum - 0*Vi] + dp[i-1][sum-1*Vi]+...+dp[i-1][sum-k*Vi]

其中k = sum / Vi
理解:拿sum=6,i=3来解释一下。其中V1=1,V2=2,V3=5,也就是Vi=5。而dp[3][6]就等于在不使用5这个硬币的时候有多少种组合方式加上使用一个5硬币有多少种组合方式。因为sum=6,最多只能有一个5硬币,所以k=1。

代码如下

int coinCombinations(int coins[], int coinKinds, int sum)
{
    vector<vector<int> > dp(coinKinds + 1, vector<int>(sum + 1, 0));

    for (int i = 0; i <= coinKinds; ++i)    //递推初始条件
    {
        dp[i][0] = 1;
    }
    for (int i = 1; i <= coinKinds; ++i)
    {
        for (int j = 1; j <= sum; ++j)
        {
            //j / coins[i-1]表示能取的该硬币的最大数量。
            //j / coins[i-1]是理解这道题的关键所在
            for (int k = 0; k <= j / coins[i - 1]; ++k)   //i-1是因为coins是从0开始算起的。
            {
                dp[i][j] += dp[i - 1][j - k * coins[i - 1]];
            }
        }
    }

    return dp[coinKinds][sum];
}

猜你喜欢

转载自blog.csdn.net/zszszs1994/article/details/80060849
今日推荐