题目链接:
求解思路:
代码:
- #include
- using namespace std;
-
- int n, bagweight;
- void solve(){
- vector<int> weight(n, 0); // 每件物品所占空间
- vector<int> value(n, 0); // 每件物品的价值
- for (int i = 0; i < n; i++){
- cin >> weight[i];
- }
- for (int j = 0; j < n; j++){
- cin >> value[j];
- }
- // 先将dp数组全部初始化为0
- vector
int>> dp(weight.size(), vector<int>(bagweight + 1, 0)); - // 当只有1件物品的时候(第一行)的初始化
- for (int j = weight[0]; j <= bagweight; j++){
- dp[0][j] = value[0];
- }
- // 开始遍历
- for (int i = 1; i < weight.size(); i++){ // 遍历物品
- for (int j = 0; j <= bagweight; j++){ // 遍历背包
- if (j < weight[i]) // 放不下的情况
- dp[i][j] = dp[i-1][j];
- else
- dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]);
- }
- }
- cout << dp[weight.size()-1][bagweight] << endl;
- }
-
- int main(){
- cin >> n >> bagweight;
- solve();
- return 0;
- }
题目链接:
求解思路:
对于背包问题其实状态都是可以压缩的。
在使用二维数组的时候,递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
其实可以发现如果把dp[i - 1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);
与其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了,只用dp[j](一维数组,也可以理解是一个滚动数组)。
这就是滚动数组的由来,需要满足的条件是上一层可以重复利用,直接拷贝到当前层。
动规五部曲
代码:
- #include
- #include
- using namespace std;
-
- int main(){
- int M, N;
- cin >> M >> N;
- vector<int> costs(M);
- vector<int> values(M);
- for (int i = 0; i < M; i++)
- cin >> costs[i];
- for (int i = 0; i < M; i++)
- cin >> values[i];
- vector<int> dp(N+1, 0);
- for (int i = 0; i < M; i++){
- for (int j = N; j >= costs[i]; j--){
- dp[j] = max(dp[j], dp[j-costs[i]] + values[i]);
- }
- }
- cout << dp[N] << endl;
- return 0;
- }
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
分割成两个等和子集,等于找出和为一半的子集,等于一个容量为数组和一半的背包可以被数组里的数装满。
注意事项
动规五部曲
代码:
- class Solution {
- public:
- bool canPartition(vector<int>& nums) {
- // 求和
- int sum = 0;
- for (int i : nums) sum+= i;
- // 和为奇数不可能有解
- if (sum % 2 == 1) return false;
- // 01背包
- int target = sum / 2;
- vector<int> dp(target+1, 0);
- for (int i = 0; i < nums.size(); i++){
- for (int j = target; j >= nums[i]; j--){
- dp[j] = max(dp[j], dp[j-nums[i]] + nums[i]);
- if (dp[j] == target) return true;
- }
- }
- return false;
- }
- };