将一组数字(n个数字)划分为2个子集,以便子集1中的数字总和与子集2中的数字总和的差异最小。此外,还需要以下条件:
答案 0 :(得分:3)
这个问题是NP完全的。 http://en.wikipedia.org/wiki/Partition_problem 你必须通过蛮力找到解决方案。
(任意大小的分区的分区问题等同于相同大小的分区的问题 - 只需向所有数字添加一个大的值C,并要求差异小于C ...)
答案 1 :(得分:0)
此答案是从http://www.careercup.com/question?id=10244832
复制而来的本质上是NP-hard,解决方案属于复数为O(n ^ 2W)的伪多项式时间算法,其中n =元素数,W =元素之和。
//constraints: n is even
void fun (int items[], int n)
{
int total = accumulate (items, items+n, 0) / 2;
int maxSubsetSz = n/2 ;
vector< vector<int> > T (maxSubsetSz+1, vector<int> (total+1, 0) );
//T[i][j] is set if there exists subset of size i that sum up to j
T[0][0] = 1;
for(int i = 0; i < n; i++) //consider taking i-th item
for(int k = maxSubsetSz-1; k >= 0; k--) //each item must be taken once, hence loop backwards
for(int j = 0; j <= total-items[i]; j++)
if ( T[k][j] && items[i]+j <= total )
T [k+1] [j+items[i]] = 1;
for(int j = total; j >= 1; j--)
if ( T [maxSubsetSz][j] ) {
cout << "sum : " << j << endl;
break;
}
}
@hugomg提供的答案具有相同的时间复杂度,因为大值C应至少与W(=元素之和)一样大,从而使背包问题的时间复杂度= O(n *(W +) nW))= O(n ^ 2 * W)