动态规划之划分数组形成两个和相等的子集

        Input: [1, 5, 11, 5]
        Output: true
        Explanation: The array can be partitioned as [1, 5, 5] and [11].

#include<iostream>
#include<vector>
using namespace std;



//dp[i]表示原数组是否可以取出若干个数字,其和为i 
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for(int i = 0 ; i < nums.size() ; i ++)
        {
        	sum += nums[i];
		}

		cout << "sum=" << sum << endl;
		
		if(sum % 2 != 0)  //判断整个和是否为偶数
			return 0;

		int target = sum / 2;
		cout << "target=" << sum/2 << endl;
		
		vector<int> dp(target + 1, 0);
		dp[i]表示原数组是否可以取出若干个数字,其和为i 
		dp[0] = 1;  //边界
		
		for(int i = 0 ; i < nums.size(); i ++)
		{
		    cout << "nums[i]=" << nums[i] << endl;
			for(int j = target; j >= nums[i]; j --)
			{   
			    //如果 dp[j - nums[i]] 为true的话,说明现在已经可以组成 j-nums[i] 这个数字了
			    //再加上nums[i],就可以组成数字j了
			    cout << "j=" << j << "," << "dp[j]=" << dp[j] << "," <<  dp[j-nums[i]] << endl;
				dp[j] = dp[j] || dp[j-nums[i]];
			}

			cout << "--------------------------------------------" <<endl;
		}
		return dp[target];
    }
};
 
int main()
{
	vector<int> temp {1, 3, 2, 4};

	Solution text;
	cout << text.canPartition(temp) << endl;
	return 0;
}

打印:

sum=10
target=5
nums[i]=1
j=5,dp[j]=0,0
j=4,dp[j]=0,0
j=3,dp[j]=0,0
j=2,dp[j]=0,0
j=1,dp[j]=0,1              //dp[1] = 1 ,数组是否可以取出若干个数字,其和为1,因为第一个数为1
--------------------------------------------
nums[i]=3
j=5,dp[j]=0,0
j=4,dp[j]=0,1            //dp[4] = 1 ,数组是否可以取出若干个数字,其和为4,因为dp[1]=1,nums[i]=3,相加和刚好是4
j=3,dp[j]=0,1            //dp[3] = 1 ,数组是否可以取出若干个数字,其和为3,刚好这个数为3
--------------------------------------------
nums[i]=2
j=5,dp[j]=0,1            //dp[5] = 1 ,数组是否可以取出若干个数字,其和为5,因为d[3]=1
j=4,dp[j]=1,0            //dp[4] = 1 ,上面已经为1了
j=3,dp[j]=1,1            //dp[3]和dp[1]都为1
j=2,dp[j]=0,1            //dp[0]为1
--------------------------------------------
nums[i]=4
j=5,dp[j]=1,1           //d[5]和dp[1]都为1
j=4,dp[j]=1,1           //d[4]和dp[0]都为1
--------------------------------------------
1

上面的思路相对数组中每个数求dp,最后就会找到dp[target]是否为true,如果 dp[j - nums[i]] 为true的话,说明现在已经可以组成 j-nums[i] 这个数字了,再加上nums[i],就可以组成数字j了。当j=target是同样道理,要想找到dp[target]为true,就找找到数组中几个值的和为target时,对应下标的dp值为true,这样反推dp[target]为true。

 

参考地址:https://blog.csdn.net/qq_40320556/article/details/89875463

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盼盼编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值