问题:
1. 有一个无序、元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组之和最接近。
采用动态规划的方法来解决问题。
题目转化为:从2n个数中选出任意个数,其和尽量接近于给定值sum/2。
外阶段:在前k个数中进行选择,k=1,2...2*n。
内阶段:从这k个数中任意选出i个数,i=1,2...k1。
状态:这i个数的和为v,v=1,2...sum/2。
决策:决定这k2个数的和有两种决策,一个是这i个数中包含第k个数,另一个是不包含第k个数。
isOK[i][v]表示从前k个数中取i个数,且这些数之和为v的取法是否存在。
代码如下:
#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++)
{
for (i=min(k,n);i>=1;i--)
{
for (v=1;v<=rem;v++)
{
if (v>=arr[k]&&(isOK[i-1][v-arr[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;
}
2. 有一个无序、元素个数为2n的正整数数组,要求:如何能把这个数组分割为两个子数组,子数组的元素个数不限,并使两个子数组之和最接近。
#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*)*(2*n+2));//内存大小改为2*n+2
for (i=0;i<=2*n;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范围到2*n
{
for (i=k;i>=1;i--)//i=min(k,n)改为i从k开始
{
for (v=1;v<=rem;v++)
{
if (v>=arr[k]&&(isOK[i-1][v-arr[k]]))
{
isOK[i][v]=1;
}
}
}
}
for (i=2;i<=2*n;i++)
{
for (v=1;v<=rem;v++)
{
if (isOK[i-1][v])
{
isOK[i][v]=1;// 表示从前i个数中取任意个数
}
}
}
v=rem;
while (v>=1&&(!isOK[2*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;
}