笔试碰到的一道题,求大神解答

输入:一个正整数数组a,最多包含50个元素,每个元素最大1000,所有元素的和最大为1000。可能包含重复元素。
找出数组中两个不相交子集,使得两个子集中元素的和相同,两个子集不一定包含a中所有元素,即可以有元素不在两个子集中。求满足这样条件的最大子集的和,不存在返回0。
例如,a=[1,2,2,2,3,4,6],子集[1,2,3,4]和[2,2,6]为满足条件的两个子集,则返回10。
a=[1,4,5,6],子集[1,5]和[6]满足条件,返回6。
求大神解答。
全部评论
const int MAX=500; bool dp[MAX+1][MAX+1]; void beibao(int weight){ for(int i=MAX;i>=0;--i){ for(int j=MAX;j>=0;--j){ if(i>=weight&&dp[i-weight][j]){ dp[i][j]=true; } if(j>=weight&&dp[i][j-weight]){ dp[i][j]=true; } } } } int getNum(int* a,int n){ memset(dp,false,sizeof(dp)); dp[0][0]=true; for(int i=0;i<n;++i) beibao(a[i]); for(int i=MAX;i>=0;--i) if(dp[i][i]) return i; } 早上想了一下,感觉可以用二重背包来写,要注意状态转移要从更大的状态开始操作,细节可参考上述代码。 复杂度为O(n*m^2)  n最大为50,m最大为500。
点赞 回复
分享
发布于 2017-09-26 09:45
貌似可以归为动态规划问题? 谷歌一下how to devide array into two equal parts
点赞 回复
分享
发布于 2017-09-25 19:56
滴滴
校招火热招聘中
官网直投
我感觉,首先求数组和sum,然后i从sum/2开始遍历到1,再数组中找和为i的子数组,看看是否存在两个不相交的子数组,存在直接返回即可。
点赞 回复
分享
发布于 2017-09-25 20:06
    想不到特别好的思路,dfs枚举所有a的子集aa,使得a-aa能拆分成2个和相同的数组(背包)。     然后需要很好的剪枝方法。。。
点赞 回复
分享
发布于 2017-09-25 20:12
_huang的思路应该可以,dp(i,j)表示截止到j和为i是否可能,然后遍历从sum/2,到1复杂度应该是50*500*500
点赞 回复
分享
发布于 2017-09-26 00:31
f(a,b,i)=f(a,b,i-1)+f(a-n[i],b,i-1)+f(a,b-n[i],i-1)迭代,上限剪枝
点赞 回复
分享
发布于 2017-09-26 05:26

相关推荐

头像
不愿透露姓名的神秘牛友
04-12 20:12
1 1 1 硕士双一流
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务