有人可以解释这个源代码进行平衡分区吗?

时间:2013-02-28 15:05:33

标签: c++

有人可以详细解释一下这段代码吗?我已经尝试过调试它,但我无法弄清楚它是如何产生结果的。我一直在寻找问题的解决方案,这是我偶然发现的代码,它产生了准确的解决方案,我想知道它是如何工作的。非常感谢。

#include <iostream>
#include <stdio.h>   
#include <math.h>
#include <stdlib.h>
#include <limits.h>
using namespace std;


int BalancedPartition ( int a[] , int n ){

int sum = 0;
for( int i = 0 ; i < n ; i++)
    sum += a[i];

int *s = new int[sum+1];

s[0] = 1;
for(int i = 1 ; i < sum+1 ; i++)    s[i] = 0;

int diff = INT_MAX , ans;

for(int i = 0 ; i < n ; i++)
{
    for(int j = sum ; j >= a[i] ; j--)
    {
        s[j] = s[j] | s[j-a[i]];
        if( s[j] == 1 )
        {
            if( diff > abs( sum/2 - j) )
            {
                diff = abs( sum/2 - j );
                ans = j;
            }

        }
    }
}
return sum-ans-ans;
}

int main()
{
    int n,result, arr[300];
    cin >>n;
    for(int i = 0; i < n; i++)
    {
        cin>>arr[i];
}
result = BalancedPartition(arr,n);
cout <<abs(result); // The difference between the sums of the two subsets

return 0;
}

1 个答案:

答案 0 :(得分:1)

函数BalancedPartition首先计算数组a元素的总和,并将其存储在sum中。然后,它分配一个数组s,该数组由可能的子集求和值索引。它用作记录结构,跟踪内部for循环的进度。如果s[j]为1,则表示已处理值j,其中值j表示数组a中某些元素子集的总和。最初,只有s[0]设置为1,这对应于无元素(空子集)的总和。 diff用于计算最接近sum值的一半的总和的子集,并且此子集求和值存储在ans中。正确计算ans后,返回的值是ansans本身未使用的元素总和之间的差异,即(sum - ans) - ans。那么,剩下的就是双for循环,看看它是如何正确到达diffans的。

外部for循环遍历i数组a的所有索引。内循环迭代j所有可能的子集求和值,从sum开始。然而,如果该值可从先前识别的子集和导出,则它仅识别子集求和值。也就是说,对于j的任何给定迭代,s[j]仅在s[j - a[i]]为1时才变为1.因为最初只识别空子集,所以第一次迭代仅识别s[a[0]] 。第二次迭代识别s[a[1]]s[a[0]+a[1]]。第三次迭代识别s[a[2]]s[a[0]+a[2]]s[a[1]+a[2]]s[a[0]+a[1]+a[2]]。如果您认识到模式,则可以为算法的正确性制定归纳论证。