序列和之差最小
来源:互联网 发布:上海811所硕士待遇知乎 编辑:程序博客网 时间:2024/05/05 07:42
问题:
有两个序列a,b,大小都为n,序列元素的值任意整数,无序;
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。例如:
var a=[100,99,98,1,2, 3];
var b=[1, 2, 3, 4,5,40];
分析:
我一开始是这么想的:循环试探a和b中元素,每次试探一个,如果和之差变小了,那么就交换元素!
代码:
#include <stdio.h>#include <math.h>#define N 6int a[10],b[10];void Exchange();void Output(int *p);int main(){int i;FILE *infile=fopen("E://a.txt","r");if (!infile){printf("The file cannot be opened!\n");return 0;}for (i=0;i<N;i++){fscanf(infile,"%d",&a[i]);}for (i=0;i<N;i++){fscanf(infile,"%d",&b[i]);}printf("Before change ,the two array are:\n");Output(a);Output(b);Exchange();printf("After change ,the two array are:\n");Output(a);Output(b);return 0;}void Exchange(){int iMinSub,iSumA,iSumB,i,j,iTemp,iTempSub;iSumA=iSumB=0;for (i=0;i<N;i++){iSumA+=a[i];iSumB+=b[i];}iMinSub=labs(iSumA-iSumB);for (i=0;i<N;i++){for (j=0;j<N;j++){iTempSub=labs(iSumA-a[i]+b[j]-(iSumB-b[j]+a[i]));if (iTempSub<iMinSub){iMinSub=iTempSub;iTemp=a[i];a[i]=b[j];b[j]=iTemp;}}}}void Output(int *p){int i;for (i=0;i<N;i++){printf("%d ",p[i]);}printf("\n");}
后来在网上看到这样的一句话:
你的做法只是每次交换一个就做判断,如果每次交换两个后做判断呢?
如果两个序列分别是[-3,9,10,65]和[5,6,13,55],按你的算法这就是最优解了。可是显然[-3,5,13,65]和[6,9,10,55]更好。
所以这个算法还是有问题的!
换种想法:
当前数组a和数组b的和之差为
A = sum(a) - sum(b)
A = sum(a) - sum(b)
a的第i个元素和b的第j个元素交换后,a和b的和之差为
A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
= sum(a) - sum(b) - 2 (a[i] - b[j])
= A - 2 (a[i] - b[j])
A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
= sum(a) - sum(b) - 2 (a[i] - b[j])
= A - 2 (a[i] - b[j])
设x = a[i] - b[j],得
|A| - |A'| = |A| - |A-2x|
|A| - |A'| = |A| - |A-2x|
假设A > 0,
当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好,
如果找不到在(0,A)之间的x,则当前的a和b就是答案。
如果找不到在(0,A)之间的x,则当前的a和b就是答案。
所以算法大概如下:
在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。
在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。
算法一(我写的):
#include <stdio.h>#include <math.h>#define N 4int a[10],b[10];void Exchange();void Output(int *p);int main(){int i;FILE *infile=fopen("E://a.txt","r");if (!infile){printf("The file cannot be opened!\n");return 0;}for (i=0;i<N;i++){fscanf(infile,"%d",&a[i]);}for (i=0;i<N;i++){fscanf(infile,"%d",&b[i]);}printf("Before change ,the two array are:\n");Output(a);Output(b);Exchange();printf("After change ,the two array are:\n");Output(a);Output(b);return 0;}void Exchange(){int iMinSub,iSumA,iSumB,i,j,x,iTemp,isChange;iSumA=iSumB=0;for (i=0;i<N;i++) //calculate sum{iSumA+=a[i];iSumB+=b[i];}iMinSub=iSumA-iSumB; //calculate subtract of two arrayfor (i=0;i<N;i++){for (j=0;j<N;j++){isChange=0; //judge if change two numberx=a[i]-b[j]; if (iMinSub>0){if (x>0&&x<iMinSub) //0<x<A{isChange=1;}}else{if (x>iMinSub&&i<0) //A<x<0{isChange=1;}}if (isChange){iTemp=a[i];a[i]=b[j];b[j]=iTemp;iMinSub-=2*x; }}}}void Output(int *p){int i;for (i=0;i<N;i++){printf("%d ",p[i]);}printf("\n");}
算法二(网上找的):
def mean(a, b): if sum(a) < sum(b): array = a a = b b = array diff_sum = sum(a) - sum(b) loop = True while loop: loop = False md = diff_sum / 2 for i in range(0, len(a)): for j in range(0, len(b)): x = a[i] - b[j] if x < diff_sum and x > 0: loop = True if abs(x - diff_sum / 2) < md: md = abs (x - diff_sum / 2) mi = i mj = j if loop: tmp = a[mi] a[mi] = b[mj] b[mj] = tmp diff_sum = diff_sum - 2 * (b[mj] - a[mi]) if diff_sum < 0: array = a a = b b = array diff_sum = - diff_sumdef main(): a = [7, 9, 10] b = [6, 2, 8] mean(a, b) print (a) print (b)if __name__ == '__main__': main()
程序如下:
#include <stdio.h>#define N 3int sum(int *a){int Sum=0,i;for (i=0;i<N;i++){Sum+=a[i];}return Sum;}void Exchange(int *a,int *b){int *array,diff_sum,loop;int i,j,x,tmp;if (sum(a)<sum(b)){array=a;a=b;b=array;}diff_sum=sum(a)-sum(b); loop=1;while (loop){loop=0;for (i=0;i<N;i++){for (j=0;j<N;j++){x=a[i]-b[j];if (x<diff_sum&&x>0){loop=1;tmp=a[i];a[i]=b[j];b[j]=tmp;diff_sum=diff_sum-2*(b[j]-a[i]);if (diff_sum<0){array=a;a=b;b=array;diff_sum=-diff_sum;}}}}}printf("After change,the items are: \n");for (i=0;i<N;i++){printf("%d ",a[i]);}printf("\n");for (i=0;i<N;i++){printf("%d ",b[i]);}printf("\n");}int main(){int i;int a[N]={7,9,10};int b[N]={6,2,8};printf("Before change,the items are: \n");for (i=0;i<N;i++){printf("%d ",a[i]);}printf("\n");for (i=0;i<N;i++){printf("%d ",b[i]);}printf("\n");Exchange(a,b);return 0;}
不知为何,还是得不出那个理想结果!
先放一下吧。。。
- 序列和之差最小
- python -- 序列和之差的绝对值最小
- py两序列和差最小
- 交换序列a,b 中的元素,使两序列的和之差最小
- 数字序列中的最大差和最小差对数
- 经典算法之6:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小
- 32.交换使两个序列差最小
- 序列a元素的和与序列b元素的和之间的差最小(32)
- 交换a,b中的元素,a序列的和 与 b序列的和 之间的差最小
- 差分序列和斯特灵数
- UVA - 1395 Slim Span(最小生成树最大边权和最小边权之差最小)
- 有两个序列a,b,要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
- 最小正序列和
- 最小m序列和
- 题目三 最大最小数之差
- 最小二乘平差之间接平差
- 最小二乘平差之条件平差
- 通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小
- 带菜单的无边框窗体
- 朴素模式配对算法
- Linux虚拟文件系统vfs及proc详解
- 顺序队列的相关代码
- html5比赛
- 序列和之差最小
- Android DialogPreference使用
- C++学习笔记:函数模版
- 教你如何贴手机膜
- Win7下安装VirtualBox
- C语言 关于fgetc 函数
- FTP命令
- Java程序员从笨鸟到菜鸟之——总结和声明
- .net集合类的研究-哈希表(一)--Hashtable,Dictionary<TKey,TValue>