题目概述:有一个没有排序,元素个数为2N的正整数数组。要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近。假设数组A[1..2N]所有元素的和是SUM。模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合。显然:S(k, 1) = {A[i] | 1<= i <= k}S(k, k) = {A[1]+A[2]+…+A[k]}S(k, i) = S(k-1, i) U {A[k] + x | x属于S(k-1, i-1) }按照这个递推公式来计算,最后找出集合S(2N, N)中与SUM最接近的那个和,这便是答案。这个算法的时间复杂度是O(2^N).
#include<iostream>
using namespace std;
int data[10]={1,5,7,8,9,6,3,11,20,17};
int main()
{
int Sum=0;
for(int i=0;i<10;i++)
Sum+=data[i];
int media[11][6][87/2+2];
for(int j=0;j<=5;j++)
for(int i=0;i<=10;i++)
for(int k=Sum/2;k>=0;k--)
media[i][j][k]=0;
for(int j=1;j<=5;j++)
{
for(int i=1;i<=10;i++)
for(int k=data[i-1];k<=Sum/2+1;k++)
{
if(0==j)
media[i][j][k]=data[i-1];
else
{
if(media[i-1][j][k]>=media[i-1][j-1][k-data[i-1]]+data[i-1])
media[i][j][k]=media[i-1][j][k];
else
media[i][j][k]=media[i-1][j-1][k-data[i-1]]+data[i-1];
}
// cout<<"(i,j,k)("<<i<<" "<<j<<" "<<k<<")"<<media[i][j][k]<<endl;
}
int a;
// cin>>a;
}
int su=media[10][5][87/2];
cout<<media[10][5][43]<<" "<<media[9][4][26]<<endl;
for(int j=5;0<j;)
for(int i=10;i>0;i--)
{
// cout<<i<<":"<<j<<" ";
// cout<<media[i][j][su]<<" "<<media[i-1][j-1][su-data[i-1]]+data[i-1]<<endl;
if(media[i][j][su]==media[i-1][j-1][su-data[i-1]]+data[i-1])
{
cout<<data[i-1]<<"**";
su=su-data[i-1];
j--;
//cout<<i<<" "<<j<<endl;
}
}
cout<<media[9][4][87/2]<<endl;
return 0;
}