leetcode 518.完全背包

完全背包

思路

朴素解法:

  • 状态划分
    • f(i,j):前i个物品凑成数量j的组合数
  • 状态转移
    • 分析:第i个物品可以选或者不选,若不选则没有新增组合数,若选择则组合数增加,即最小的情况就是不选
    • 因此:f[i][j] = f[i-1][j] + sum(f[i-1][j - k*value]) , k >= 1, k * val <= j

代码

class Solution {
    int dp[305][5005];
public:
    int change(int amount, vector<int>& coins) {
        int n = coins.size();
        for(int i = 0;i <= n;i++)   dp[i][0] = 1;
        for(int i = 1;i <= coins.size();i++){
            for(int j = 0;j <= amount;j++){
                dp[i][j] = dp[i-1][j];
                for(int k = 1;k * coins[i-1] <= j;k++){
                    // 这里的状态转移是由上一轮得到的,所以要进行累和
                    dp[i][j] += dp[i-1][j - k * coins[i-1]];
                }
            }
        }
        return dp[n][amount];
    }
};

思路

时间优化:
在朴素解法的基础上,可以将k省去
因为在朴素解法中,每次第i维的状态,都是由第i-1维的状态转移过来的,实际上可以使用第i维来转移。由于dp[i][j - value]其实就是 sum(dp[i-1][j-k*value])
则可以得到更简洁的状态转移方程:

  • f[i][j] = f[i-1][j] + f[i][j-value]

代码

class Solution {
    int dp[305][5005];
public:
    int change(int amount, vector<int>& coins) {
        int n = coins.size();
        for(int i = 0;i <= n;i++)   dp[i][0] = 1;
        for(int i = 1;i <= n;i++){
            for(int j = 0;j <= amount;j++){
                dp[i][j] = dp[i-1][j];
                if(j - coins[i-1] >= 0) dp[i][j] += dp[i][j-coins[i-1]];
            }
        }
        return dp[n][amount];
    }
};

思路:

空间优化:
空间优化就非常简单了,直接把第一维去掉就好了,因为每次第i维j列的数据,都是由j列前的数据得到的,用一维模拟这个过程完全没有歧义

代码:

class Solution {
    int dp[5005];
public:
    int change(int amount, vector<int>& coins) {
        int n = coins.size();
        dp[0] = 1;
        for(int i = 1;i <= n;i++){
            for(int j = coins[i-1];j <= amount;j++){
                dp[j] += dp[j-coins[i-1]];
            }
        }
        return dp[amount];
    }
};
posted @   andandan  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
点击右上角即可分享
微信分享提示