动态规划:NC126_换钱最少货币数

更多动态规划,参考牛客网总结:动态规划

目录

 1.题目介绍

2.01背包

3.完全背包

4.本题解法

5.参考文献 


 1.题目介绍

此题是一个完全背包问题,是一个经典的动态规划问题,想要理解完全背包的状态转移过程,首先需要理解01背包。所以,下面先介绍01背包和完全背包。 

2.01背包

 3.完全背包

具体代码如下: 

int DP() {
    for(int i = 1; i <= M; i++)
        f[0][j] = -inf; // 负无穷,inf 可以为 1e8
    f[0][0] = 0;
    for(int i = 1; i <= N; i++)
        for(int j = 0; j <= M; j++)
            if(j >= v[i])
                f[i][j] = max(f[i-1][j], f[i][j-v[i]] + w[i]);
            else
                f[i][j] = f[i-1][j];
    int ans = 0;
    for(int i = 0; i <= M; i++)
        ans = max(ans, f[N][i]);
    return ans;
}

 我们还可以将上述代码优化为:

int DP() {
    for(int i = 1; i <= M; i++)
        f[j] = -inf; // 负无穷,inf 可以为 1e8
    f[0] = 0;
    for(int i = 1; i <= N; i++)
        for(int j = v[i]; j <= M; j++)
            f[j] = max(f[j], f[j-v[i]] + w[i]);
    int ans = 0;
    for(int i = 0; i <= M; i++)
        ans = max(ans, f[i]);
    return ans;
}

 4.本题解法

如果我们将面值看作是物品,面值金额看成是物品的重量,每件物品的价值均为1,这样此题就是是一个恰好装满的完全背包问题了。不过这里不是求最多装入多少物品而是求最少,我们只需要将2.2节的转态转移方程中的max改成min即可,又由于是恰好装满,所以除了dp[0],其他都应初始化为INT_MAX。完整代码如下:

int coinChange(vector<int>& coins, int amount) {
    vector<int>dp(amount + 1, INT_MAX);
    dp[0] = 0;

    for(int i = 1; i <= coins.size(); i++)
        for(int j = coins[i-1]; j <= amount; j++){
            // 下行代码会在 1+INT_MAX 时溢出
            // dp[j] = min(dp[j], 1 + dp[j - coins[i-1]]); 
            if(dp[j] - 1 > dp[j - coins[i-1]])
                dp[j] = 1 + dp[j - coins[i-1]];   
        }
    return dp[amount] == INT_MAX ? -1 : dp[amount];   
}

注意上面1 + dp[j - coins[i-1]]会存在溢出的风险,所以我们换了个写法。 

5.参考文献 

算法萌新如何学好动态规划(3)

动态规划之背包问题系列

猜你喜欢

转载自blog.csdn.net/haimianjie2012/article/details/110846998