首页 > 代码库 > 数组分割

数组分割

将大小为2N的数组分成两个大小为N的数组,使得两个子数组之和最接近

#include<iostream>

using namespace std;

#define min(a,b) (((a)<=(b))?(a):(b))

void function(int arr[],int n)

{

int sum=0;

int i;

int rem;

int **isOK;

int k;

int v;

for (i=1;i<=2*n;i++)

{

sum += arr[i];

}

rem=sum/2;

isOK=(int **)malloc(sizeof(int*)*(n+3));

for (i=0;i<=n+1;i++)

{

isOK[i]=(int *)malloc(sizeof(int)*(sum+2));

memset(isOK[i],0,sizeof(isOK[i])*(sum+2));//动态分配内存之后初始化。

}

 

 

isOK[0][0]=1;

for (k=1;k<=2*n;k++)

{//对于前K个数的情况

for (i=1;i=min(k,n);i++)

//这里FOR循环I必须是递增,不能是递减,因为否则下面的isOK[i-1][v-arr[k]]会导致某个i会在前一个i-1中继续加上arr[k],导致arr[k]被使用两次

{

//这一层循环的目的在于对于正在考虑的元素arr[k],它加入进来后,该子集的个数是不确定的,因此需要逐步遍历考虑。可能前k个全部加入,也可能只是1k两个元素。

//从前K个数里面,选择i个数。当k>n时,表示考虑到了后面n个,但是最多只能取n个。这里考虑的是从2n中取出n个,并且使得这n个之和最接近sum/2

for (v=1;v<=rem;v++)

{

if (v>=arr[k]&&(isOK[i-1][v-arr[k]]))

//这里的i表示有多少个元素

当前只考虑是否把第k个元素是否加入进来

{

isOK[i][v]=1;

}

}

}

}

 

 

v=rem;

while (v>=1&&(!isOK[n][v]))

{

v--;

}

cout<<"两个数组的差为:"<<sum-2*v<<endl;

}

int main()

{

int n;

int *arr;

int i;

cout<<"请输入 n : ";

cin>>n;

arr=(int *)malloc(sizeof(int)*(n+2));

cout<<"请输入 "<<2*n<<"个数字:"<<endl;

for (i=1;i<=2*n;i++)

{

cin>>arr[i];

}

function(arr,n);

return 0;

}

数组分割