背包型动态规划

01背包

不带价值的01背包,求最优解

92. 背包问题
解法1:背包型DP

class Solution {
public:
    int backPack(int m, vector<int> &a) {
        int n = a.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));

        // initial
        // dp[0][0 to m] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                if (j >= a[i - 1]) {
                    dp[i][j] = max(dp[i - 1][j],
                        dp[i - 1][j - a[i - 1]] + a[i - 1]);
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][m];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int backPack(int m, vector<int> &a) {
        int n = a.size();

        // state
        vector<int> dp(m + 1);

        // initial
        // dp[0 to m] = 0;

        // function
        for (int i = 0; i < n; ++i) {
            for (int j = m; j >= a[i]; --j) {
                dp[j] = max(dp[j], dp[j - a[i]] + a[i]);
            }
        }

        // answer
        return dp[m];
    }
};
不带价值的01背包,求方案数

563. 背包问题 V
解法1:背包型DP

class Solution {
public:
    int backPackV(vector<int> &nums, int target) {
        int n = nums.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(target + 1));

        // initial
        dp[0][0] = 1;
        // dp[0][1 to target] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= target; ++j) {
                if (j >= nums[i - 1]) {
                    dp[i][j] = dp[i - 1][j] + 
                        dp[i - 1][j - nums[i - 1]];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][target];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int backPackV(vector<int> &nums, int target) {
        int n = nums.size();

        // state
        vector<int> dp(target + 1);

        // initial
        dp[0] = 1;
        // dp[1 to target] = 0;

        // function
        for (int i = 0; i < n; ++i) {
            for (int j = target; j >= nums[i]; --j) {
                dp[j] += dp[j - nums[i]];
            }
        }

        // answer
        return dp[target];
    }
};
带价值的01背包,求最优解

125. 背包问题 II
解法1:背包型DP

class Solution {
public:
    int backPackII(int m, vector<int> &a, vector<int> &v) {
        int n = a.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));

        // initial
        // dp[0][0 to m] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                if (j >= a[i - 1]) {
                    dp[i][j] = max(dp[i - 1][j],
                        dp[i - 1][j - a[i - 1]] + v[i - 1]);
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][m];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int backPackII(int m, vector<int> &a, vector<int> &v) {
        int n = a.size();

        // state
        vector<int> dp(m + 1);

        // initial
        // dp[0 to m] = 0;

        // function
        for (int i = 0; i < n; ++i) {
            for (int j = m; j >= a[i]; --j) {
                dp[j] = max(dp[j], dp[j - a[i]] + v[i]);
            }
        }

        // answer
        return dp[m];
    }
};
分割等和子集

416. 分割等和子集
解法1:背包型DP

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int n = nums.size();
        int sum = accumulate(nums.begin(), nums.end(), 0);
        if (sum % 2) {
            return false;
        }
        int m = sum / 2;
        
        // state
        vector<vector<bool>> dp(n + 1, vector<bool>(m + 1));

        // initial
        dp[0][0] = true;
        // dp[0][1 to m] = false;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                if (j >= nums[i - 1]) {
                    dp[i][j] = dp[i - 1][j] ||
                        dp[i - 1][j - nums[i - 1]];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][m];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int n = nums.size();
        int sum = accumulate(nums.begin(), nums.end(), 0);
        if (sum % 2) {
            return false;
        }
        int m = sum / 2;
        
        // state
        vector<bool> dp(m + 1);

        // initial
        dp[0] = true;
        // dp[1 to m] = false;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = m; j >= nums[i - 1]; --j) {
                dp[j] = dp[j] || dp[j - nums[i - 1]];
            }
        }

        // answer
        return dp[m];
    }
};
最后一块石头的重量 II

1049. 最后一块石头的重量 II
解法1:背包型DP

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int n = stones.size();
        int sum = accumulate(stones.begin(), stones.end(), 0);
        int m = sum / 2;

        // state
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));

        // initial
        // dp[0][0 to m] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                if (j >= stones[i - 1]) {
                    dp[i][j] = max(dp[i - 1][j],
                        dp[i - 1][j - stones[i - 1]] + stones[i - 1]);
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return sum - 2 * dp[n][m];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int n = stones.size();
        int sum = accumulate(stones.begin(), stones.end(), 0);
        int m = sum / 2;

        // state
        vector<int> dp(m + 1);

        // initial
        // dp[0][0 to m] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = m; j >= stones[i - 1]; --j) {
                dp[j] = max(dp[j],
                    dp[j - stones[i - 1]] + stones[i - 1]);
            }
        }

        // answer
        return sum - 2 * dp[m];
    }
};
目标和

494. 目标和
解法1:DFS

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int count = 0;
        dfs(nums, target, 0, count);
        return count;
    }

    void dfs(
        vector<int>& vec, int sum,
        int start, int& count
    ) {
        if (start == vec.size()) {
            if (sum == 0) {
                ++count;
            }
            return;
        }
        dfs(vec, sum - vec[start], start + 1, count);
        dfs(vec, sum + vec[start], start + 1, count);
    }
};

解法2:背包型DP

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int n = nums.size();
        int sum = accumulate(nums.begin(), nums.end(), 0);
        if (abs(target) > sum) {
            return 0;
        }
        if ((target + sum) % 2) {
            return 0;
        }
        int m = (target + sum) / 2;

        // state
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));

        // initial
        dp[0][0] = 1;
        // dp[0][1 to m] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                if (j >= nums[i - 1]) {
                    dp[i][j] = dp[i - 1][j] +
                        dp[i - 1][j - nums[i - 1]];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][m];
    }
};

解法3:背包型DP+滚动数组

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int n = nums.size();
        int sum = accumulate(nums.begin(), nums.end(), 0);
        if (abs(target) > sum) {
            return 0;
        }
        if ((target + sum) % 2) {
            return 0;
        }
        int m = (target + sum) / 2;

        // state
        vector<int> dp(m + 1);

        // initial
        dp[0] = 1;
        // dp[1 to m] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = m; j >= nums[i - 1]; --j) {
                dp[j] += dp[j - nums[i - 1]];
            }
        }

        // answer
        return dp[m];
    }
};
一和零

474. 一和零
解法1:背包型DP+滚动数组

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        // state
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        
        // initial
        // dp[0 to m][0] = 0, dp[0][0 to n] = 0;

        for (const auto& s: strs) {
            int n0 = 0, n1 = 0;
            for (const char& c: s) {
                if (c == '0') {
                    ++n0;
                }
                if (c == '1') {
                    ++n1;
                }
            }
            // function
            for (int i = m; i >= n0; --i) {
                for (int j = n; j >= n1; --j) {
                    dp[i][j] = max(dp[i][j],
                        dp[i - n0][j - n1] + 1);
                }
            }
        }

        // answer
        return dp[m][n];
    }
};

完全背包

不带价值的完全背包,求方案数

562. 背包问题 IV
解法1:背包型DP

class Solution {
public:
    int backPackIV(vector<int> &nums, int target) {
        int n = nums.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(target + 1));

        // initial
        dp[0][0] = 1;
        // dp[0][1 to target] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= target; ++j) {
                if (j >= nums[i - 1]) {
                    dp[i][j] = dp[i - 1][j] +
                        dp[i][j - nums[i - 1]];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][target];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int backPackIV(vector<int> &nums, int target) {
        int n = nums.size();

        // state
        vector<int> dp(target + 1);

        // initial
        dp[0] = 1;
        // dp[1 to target] = 0;

        // function
        for (int i = 0; i < n; ++i) {
            for (int j = nums[i]; j <= target; ++j) {
                dp[j] += dp[j - nums[i]];
            }
        }

        // answer
        return dp[target];
    }
};
带价值的完全背包,求最优解

440. 背包问题 III
解法1:背包型DP

class Solution {
public:
    int backPackIII(vector<int> &a, vector<int> &v, int m) {
        int n = a.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));

        // initial
        // dp[0][0 to m] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                if (j >= a[i - 1]) {
                    dp[i][j] = max(dp[i - 1][j],
                        dp[i][j - a[i - 1]] + v[i - 1]);
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][m];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int backPackIII(vector<int> &a, vector<int> &v, int m) {
        int n = a.size();

        // state
        vector<int> dp(m + 1);

        // initial
        // dp[0][0 to m] = 0;

        // function
        for (int i = 0; i < n; ++i) {
            for (int j = a[i]; j <= m; ++j) {
                dp[j] = max(dp[j], dp[j - a[i]] + v[i]);
            }
        }

        // answer
        return dp[m];
    }
};
零钱兑换 II

518. 零钱兑换 II
解法1:背包型DP

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        int n = coins.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(amount + 1));

        // initial
        dp[0][0] = 1;
        // dp[0][1 to amount] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= amount; ++j) {
                if (j >= coins[i - 1]) {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i - 1]];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][amount];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        int n = coins.size();

        // state
        vector<int> dp(amount + 1);

        // initial
        dp[0] = 1;
        // dp[1 to amount] = 0;

        // function
        for (int i = 0; i < n; ++i) {
            for (int j = coins[i]; j <= amount; ++j) {
                dp[j] += dp[j - coins[i]];
            }
        }

        // answer
        return dp[amount];
    }
};
377. 组合总和 IV

377. 组合总和 IV
解法1:背包型DP

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        int n = nums.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(target + 1));

        // initial
        for (int i = 0; i <= n; ++i) {
            dp[i][0] = 1;
        }

        // function
        for (int j = 1; j <= target; ++j) {
            for (int i = 1; i <= n; ++i) {
                for (int k = i; k > 0; --k) {
                    if (j >= nums[k - 1] &&
                        dp[i][j] < INT_MAX - dp[i][j - nums[k - 1]]) {
                        dp[i][j] += dp[i][j - nums[k - 1]];
                    }
                }
            }
        }

        // answer
        return dp[n][target];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        int n = nums.size();

        // state
        vector<int> dp(target + 1);

        // initial
        dp[0] = 1;
        // dp[1 to target] = 0;

        // function
        for (int j = 0; j <= target; ++j) {
            for (int i = 0; i < n; ++i) {
                if (j >= nums[i] &&
                    dp[j] < INT_MAX - dp[j - nums[i]]) {
                    dp[j] += dp[j - nums[i]];
                }
            }
        }

        // answer
        return dp[target];
    }
};
爬楼梯

70. 爬楼梯
解法1:坐标型DP

class Solution {
public:
    int climbStairs(int n) {
        // state
        vector<int> dp(n + 1);

        // initial
        dp[0] = dp[1] = 1;

        // function
        for (int i = 2; i <= n; ++i) {
            dp[i] = dp[i - 2] + dp[i - 1];
        }
        
        // answer
        return dp[n];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int climbStairs(int n) {
        // state
        vector<int> dp(n + 1);

        // initial
        dp[0] = 1;

        // function
        for (int j = 1; j <= n; ++j) {
            for (int i = 1; i <= 2; ++i) {
                if (j >= i) {
                    dp[j] += dp[j - i];
                }
            }
        }

        // answer
        return dp[n];
    }
};
零钱兑换

322. 零钱兑换
解法1:背包型DP

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();

        // state
        vector<vector<int>> dp(n + 1, vector<int>(amount + 1));

        // initial
        fill(dp[0].begin(), dp[0].end(), INT_MAX);
        dp[0][0] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= amount; ++j) {
                if (j >= coins[i - 1] &&
                    dp[i][j - coins[i - 1]] < INT_MAX) {
                    if (dp[i - 1][j] < INT_MAX) {
                        dp[i][j] = min(dp[i - 1][j],
                            dp[i][j - coins[i - 1]] + 1);
                    } else {
                        dp[i][j] = dp[i][j - coins[i - 1]] + 1;
                    }
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][amount] == INT_MAX ? -1 : dp[n][amount];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int n = coins.size();

        // state
        vector<int> dp(amount + 1, INT_MAX);

        // initial
        dp[0] = 0;
        // dp[1 to amount] = INT_MAX;

        // function
        for (int i = 0; i < n; ++i) {
            for (int j = coins[i]; j <= amount; ++j) {
                if (dp[j - coins[i]] < INT_MAX) {
                    dp[j] = min(dp[j], dp[j - coins[i]] + 1);
                }
            }
        }

        // answer
        return dp[amount] == INT_MAX ? -1 : dp[amount];
    }
};
完全平方数

279. 完全平方数
解法1:背包型DP

class Solution {
public:
    int numSquares(int n) {
        // state
        vector<vector<int>> dp(n + 1, vector<int>(n + 1));

        // initial
        fill(dp[0].begin(), dp[0].end(), INT_MAX);
        dp[0][0] = 0;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j <= n; ++j) {
                if (j >= i * i) {
                    dp[i][j] = min(dp[i - 1][j],
                        dp[i][j - i * i] + 1);
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        // answer
        return dp[n][n];
    }
};

解法2:背包型DP+滚动数组

class Solution {
public:
    int numSquares(int n) {
        // state
        vector<int> dp(n + 1, INT_MAX);

        // initial
        dp[0] = 0;
        // dp[1 to n] = INT_MAX;

        // function
        for (int i = 1; i <= n; ++i) {
            for (int j = i * i; j <= n; ++j) {
                dp[j] = min(dp[j], dp[j - i * i] + 1);
            }
        }

        // answer
        return dp[n];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值