我知道这里谈了很多,但我正在努力解决这个问题。
我们有一组数字,例如[3,1,1,2,2,1],我们需要将它分成两个子集,因此每个总和相等或差异最小。
我见过wikipedia entry,此page(问题7)和blog entry。
但列出的每个算法只给出YES / NO结果,我真的不明白如何使用它们打印出两个子集(例如S1 = {5,4}和S2 = {5,3,3}) 。我在这里缺少什么?
答案 0 :(得分:4)
伪多项式算法旨在为决策问题提供答案,而不是优化问题。但请注意,the example中布尔表中的最后一行表示当前集合能够总计为N / 2.
在最后一行,取第一列,其中布尔值为true
。然后,您可以检查给定列中集合的实际值。如果集合求和值为N / 2,则找到第一组分区。否则你必须检查哪个集合能够与N / 2不同。你可以使用与上面相同的方法,这次是差异 d 。
答案 1 :(得分:1)
这将是 O(2 ^ N)。这里没有使用动态编程。您可以在执行该函数后打印result1,result2和差异。我希望这会有所帮助。
vector<int> p1,p2;
vector<int> result1,result2;
vector<int> array={12,323,432,4,55,223,45,67,332,78,334,23,5,98,34,67,4,3,86,99,78,1};
void partition(unsigned int i,long &diffsofar, long sum1,long sum2)
{
if(i==array.size())
{
long diff= abs(sum1 - sum2);
if(diffsofar > diff)
{
result1 = p1;
result2 = p2;
diffsofar = diff;
}
return;
}
p1.push_back(array[i]);
partition(i+1,diffsofar,sum1+array[i],sum2);
p1.pop_back();
p2.push_back(array[i]);
partition(i+1,diffsofar,sum1,sum2+array[i]);
p2.pop_back();
return;
}
答案 2 :(得分:0)
我最近遇到了同样的问题,我发布了一个关于它的问题(这里:Variant of Knapsack)。我的情况不同,结果子集必须是相同的大小(如果原始集具有偶数个元素)。为了确保这一点,我在@Sandesh Kobal回答中加了几行;
void partition(unsigned int i,long &diffsofar, long sum1,long sum2)
{
int maxsize = (array.size()+1)/2;
if(p1.size()>maxsize)
return;
if(p2.size()>maxsize)
return;
if(i==array.size())
{
...
此外,在同时拨打partition
之后,我添加了if(diffsofar==0) return;
。如果我们已经找到了最佳解决方案,那么继续搜索是没有意义的......