问题重现:
有两个数组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<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); }