平衡分区

时间:2012-10-08 11:51:22

标签: algorithm

我知道这里谈了很多,但我正在努力解决这个问题。

我们有一组数字,例如[3,1,1,2,2,1],我们需要将它分成两个子集,因此每个总和相等或差异最小。

我见过wikipedia entry,此page(问题7)和blog entry

但列出的每个算法只给出YES / NO结果,我真的不明白如何使用它们打印出两个子集(例如S1 = {5,4}和S2 = {5,3,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;。如果我们已经找到了最佳解决方案,那么继续搜索是没有意义的......