问题重现:
有两个数组a,b,大小都为n,数组元素的值任意,无序;
要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小。
分析:
和差最小,也就是找出一组长度为n且和值在avg*len附近的数的组合,余下的数在另一组中。
以下代码仅打印出一组最合适的组合,通过穷举,未追求效率
#include<stdio.h>
/*求平均值*/
int myAvg(int *a,int *b,int len){
int count=0,i;
for(i=0;i<len;i++){
//a和b数组长度相等
count+=a[i]+b[i];
}
return count/(len*2);
}
/*打印组合*/
void printGroup(int *aa,int *bb,int len){
int i;
for(i=0;i<len;i++){
printf("%d ",aa[i]);
}
printf(",");
for(i=0;i<len;i++){
printf("%d ",bb[i]);
}
printf("\n");
}
/*求所有组合,最后只选举出一个最合适的结果 作者:天之*/
void allGroup(int *a,int *b,int i,int len2,int result,int dis,int *res,int *aa,int *bb){
if(i==len2){
int m,len=len2/2,count=0,tmp,times=0;
for(m=0;m<len2;m++){
if(res[m]==1 && m<len){
count+=a[m];
times++;
}
if(res[m]==1 && m>=len){
count+=b[m-len];
times++;
}
}
tmp=result-count;
if(tmp>=0 && tmp<dis && times==len){
dis=tmp;
for(m=0;m<len2;m++){
if(res[m]==1 && m<len){
//printf("%d ",a[m]);
*aa++=a[m];
}
if(res[m]==1 && m>=len){
//printf("%d ",b[m-len]);
*aa++=b[m-len];
}
}
//printf(",");
for(m=0;m<len2;m++){
if(res[m]==0 && m<len){
//printf("%d ",a[m]);
*bb++=a[m];
}
if(res[m]==0 && m>=len){
//printf("%d ",b[m-len]);
*bb++=b[m-len];
}
}
//printf("\n");
}
return;
}
res[i]=0;
allGroup(a,b,i+1,len2,dis,result,res,aa,bb);
res[i]=1;
allGroup(a,b,i+1,len2,dis,result,res,aa,bb);
}
void main(){
int a[]={12,33,22,11,55};
int b[]={23,11,22,31,67};
int len=5;
int avg=myAvg(a,b,len);
int res[10];
int aa[5];
int bb[5];
allGroup(a,b,0,len*2,avg*len,a[0],res,aa,bb);
printGroup(aa,bb,len);
}