Chinaunix首页 | 论坛 | 博客
  • 博客访问: 68435
  • 博文数量: 46
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-23 18:23
文章分类
文章存档

2014年(2)

2013年(44)

我的朋友

分类: C/C++

2013-07-04 10:10:41

有两个数组a,b,大小都为n,数组元素的值任意,无序;
要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
 
思路:
用二重循环把a中的每个元素和b中的每个元素逐个“尝试交换”,
如果是差值变小就维持交换,否则就交换回去,也就是不交换,
每有一次交换,“尝试交换”的二重循环就重新从头开始,
直到没有任何交换使差值变小为止。
这种方法不是很简洁,但的确是可行的。
前边贴出代码的算法,有过一次交换后,循环没有从头开始,所以是错误的。例如a[1]和b[j]交换后,b中的元素改变了,不能再保证a[0]和b[ i ]交换不会使差值变小,这时循环必须从头开始。
 
实现代码:
  1. #include <stdio.h>
  2. #include <math.h>

  3. #define N 10

  4. void ary_init(int a[], int b[]){ //初始化数组
  5.     int i;
  6.     for (i=0; i<N; i++){
  7.         a[i] = rand()%10000;
  8.     }
  9.     for (i=0; i<N; i++){
  10.         b[i] = rand()%100;
  11.     }
  12.     return;
  13. }
  14. long sum(int a[]){ //数组求和
  15.     int i;
  16.     int s;
  17.     for (s=0,i=0; i<N; i++){
  18.         s += a[i];
  19.     }
  20.     return s;
  21. }

  22. void change(int *a, int *b){ //数组元素交换
  23.     int tmp;
  24.     tmp = *a;
  25.     *a = *b;
  26.     *b = tmp;
  27.     return;
  28. }

  29. void prt_ary(int a[], int b[]){ //列印两数组元素及各自元素和
  30.     int i;
  31.     for(i=0; i<N; i++){
  32.         printf("%5d ", a[i]);
  33.     }
  34.     printf("\n");
  35.     for(i=0; i<N; i++){
  36.         printf("%5d ", b[i]);
  37.     }
  38.     printf("\n");
  39.     printf("%d\n", sum(a));
  40.     printf("%d\n", sum(b));
  41. }
  42. int slove(int a[], int b[]){
  43.     int i;
  44.     int j;
  45.     int is_swap = 0;//是否修交换过数据标志
  46.     int ab_diff;

  47.     ab_diff = abs(sum(a)-sum(b));
  48.     for (i=0; i<N; i++){
  49.         for (j=0; j<N; j++){
  50.             change(a+i, b+j);
  51.             if (abs(sum(a)-sum(b)) < ab_diff){//判断是否需要交换元素
  52.                 is_swap = 1; //置位交换标志
  53.                 ab_diff = abs(sum(a)-sum(b)); //更新差值
  54.             }
  55.             else{
  56.                 change(b+j, a+i);//不交换

  57.             }
  58.         }
  59.     }
  60.     return is_swap;
  61. }
  62. int main(){

  63.     int a[N];
  64.     int b[N];

  65.     ary_init(a,b);//数组元素初始化
  66.     prt_ary(a, b);//列印当前数组状态
  67.     while (slove(a, b));//处理数组
  68.     prt_ary(a, b);//列印交换后数组状态
  69.     getch();
  70. }

本文根据cu精华贴整理而来,在此对代码贡献者表示感谢:

阅读(298) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

miao_lear2018-11-10 00:08:17

例子如下:
a : 12,25,98,78 sum_a=213
b : 67,37,92,23 sum_b=219
A=219-213=6
此时遍历a,b找不到一对可交换的数据了。
但是,存在同时交换两对数据的情况可以使得差更小
最优解如下:
a : 12,98,67,37 sum_a=214
b : 23,78,92,25 sum_b=218
A=4

miao_lear2018-11-10 00:05:43

博主,这个方法看起来简单直观,却是有问题的,可能会找不到最小值
因为找不到一对可交换的数据使得差变小,不代表已经是最优解了,因为可能存在同时交换多对的情况使得差更小。