有人可以详细解释一下这段代码吗?我已经尝试过调试它,但我无法弄清楚它是如何产生结果的。我一直在寻找问题的解决方案,这是我偶然发现的代码,它产生了准确的解决方案,我想知道它是如何工作的。非常感谢。
#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;
}
答案 0 :(得分:1)
函数BalancedPartition
首先计算数组a
元素的总和,并将其存储在sum
中。然后,它分配一个数组s
,该数组由可能的子集求和值索引。它用作记录结构,跟踪内部for
循环的进度。如果s[j]
为1,则表示已处理值j
,其中值j
表示数组a
中某些元素子集的总和。最初,只有s[0]
设置为1,这对应于无元素(空子集)的总和。 diff
用于计算最接近sum
值的一半的总和的子集,并且此子集求和值存储在ans
中。正确计算ans
后,返回的值是ans
和ans
本身未使用的元素总和之间的差异,即(sum - ans) - ans
。那么,剩下的就是双for
循环,看看它是如何正确到达diff
和ans
的。
外部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]]
。如果您认识到模式,则可以为算法的正确性制定归纳论证。