LeetCode-- Daily -- 动态规划 --背包问题

LeetCode-- Daily – 动态规划 --背包问题

416.分割等和子集(0-1背包)

AC代码 1 (普通动态规划流程):

class Solution {
public:
    bool canPartition1(vector<int>& nums) {
		int n = nums.size(), sum_nums = accumulate(nums.begin(), nums.end(), 0);
		if (sum_nums % 2) return false;
		sum_nums = sum_nums / 2;
		vector<vector<int>> dp(n+1 , vector<int>(sum_nums + 1, false));
		dp[0][0] = true;
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j <= sum_nums; j++) {
				if (nums[i - 1] <= j)
					dp[i][j]  = dp[i-1][j] || dp[i - 1][j - nums[i-1]];
				else dp[i][j] = dp[i-1][j];
				//cout<<dp[i][j]<<" " ;
			}
			//cout << endl;
		}
		return dp[n][sum_nums];
	}
};

AC代码 2 (压缩空间):

class Solution {
public:
  	 bool canPartition(vector<int>& nums) {
		int n = nums.size(), sum_nums = accumulate(nums.begin(), nums.end(), 0);
		if (sum_nums % 2) return false;
		sum_nums = sum_nums / 2;
		vector<int> dp(sum_nums + 1, false);
		dp[0] = true;
		for (int i = 1; i <= n; i++) {
			for (int j = sum_nums;  nums[i - 1] <= j; j--) {
					dp[j]  = dp[j] || dp[j - nums[i-1]];
			}
		}
		return dp[sum_nums];
	}
};

解题思路总结:

1. ** dp矩阵的含义* *:dp[i][j]: num[0:i-1]是否能满足背包装下j的物品
2. **递推公式**:两种情况 -- 放入背包 和 不放入背包
      &emsp;&emsp;&emsp;  能放入背包:  放入num[i-1]前的dp值(即dp[i-1][j-nums[i]]) ||   num[0:i-2]是否能满足j的背包容量(dp[i-1][j])
        &emsp;&emsp;&emsp; 不能放入背包:num[0:i-2]是否能满足j的背包容量(dp[i-1][j])
3. **循环位置的确定**:为什么 j 从0开始:保证dp[ : ][0]都是True,因为dp向前回溯时会用到左上的值,如果想从1开始,可以在dp初始化时改变第一列的值。
4. **使用压缩空间的方法时**:相当于在构建dp矩阵时忽略物品的维度, 且循环顺序改为倒序(避免是重复放入),循环的停止条件直接选用循环内的截至条件,减少了代码量。

474.一和零(0-1背包)

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        int count1=0,count0=0;
        for(const string &str :strs){
            count0 =0,count1=0;
            for(const char & c :str){
                if (c=='1') count1++;
                else count0++;
            }
            for(int i=m;i>=count0;i--){
                for(int j=n;j>=count1;j--){
                    dp[i][j] = max(dp[i][j],1+dp[i-count0][j-count1]);
                }
            }
        }
        return dp[m][n];
    }
};

解题思路总结:

0. 此题目有三个变量,之前一直是背包1维,物品一维,现在背包成了二维( m 个1以及 n 个0),如果普通的套路需要将dp矩阵初始化成三维,相对麻烦,因此将dp矩阵初始化为m*n的,相当于从3维数组压缩空间至2维数组。
1. dp的含义 :dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。
2. 递推公式 :dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
            加入物品前的dp状态+1 和 本身的状态取最大值
3. 物品1维,背包2维,如果要使用二维的dp,则需要压缩空间,将背包的size作为dp的大小,且初始化为0即可
4. 循环顺序:压缩空间则是倒序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值