- 论坛徽章:
- 0
|
没想出好的算法 我的思路把2n个数放在一个数组里 然后用组合找出n个数 求和 另n个数也求和 做查
求出所有这样的差值的最小值,故复杂度为theta( C(2n, n))再把原数组的值经过有限次的交换 调整成最优解的数组值就行了
其中C(2n, n)用的是回溯 构架是
- void select_combination(int l, int p)
- {
- int i;
- if (l == n)
- {
- 。。。
- return;
- }
- for(i=p; i<=2*n-(n-l); ++i) //上个位置填的是num[p-1],本次从num[p]开始试探
- {
- b[i] = true;
- select_combination(l+1, i+1); //填下一个位置
- b[i] = false;
- }
- }
复制代码
下面是整个程序
- #include <stdio.h>
- #include <math.h>
- const int n = 3;
- int num[2*n];
- bool b[2*n];
- bool bc[2*n];
- bool first = true;
- int de, sumae, sumbe;
- int mins;
- void copy(bool p[], bool q[], int n)
- {
- for (int i = 0; i < n; ++i)
- {
- q[i] = p[i];
- }
- }
- void select_combination(int l, int p)
- {
- int i;
- if (l == n)
- {
- int suma = 0, sumb = 0;
- for (i=0; i<2*n; ++i)
- {
- if (b[i])
- suma += num[i];
- else
- sumb += num[i];
- }
- if (first)
- {
- first = false;
- mins = abs(suma - sumb);
- de = mins;
- sumae = suma;
- sumbe = sumb;
- }
-
- else
- {
- int d = abs(suma - sumb);
- if (d < mins)
- {
- mins = d;
- copy(b, bc, 2*n);
- de = mins;
- sumae = suma;
- sumbe = sumb;
- }
- }
- return;
- }
- for(i=p; i<=2*n-(n-l); ++i) //上个位置填的是num[p-1],本次从num[p]开始试探
- {
- b[i] = true;
- select_combination(l+1, i+1); //填下一个位置
- b[i] = false;
- }
- }
- bool find(int a[], int n, int va, int& pos)
- {
- for (int i = 0; i < n; ++i)
- {
- if (va == a[i])
- {
- pos = i;
- return true;
- }
- }
- return false;
- }
- void swap(int& a, int& b)
- {
- int tem = a;
- a = b;
- b = tem;
- }
- int main()
- {
- int a[n] = {1,4, 7};
- int c[n] = {2,5,12};
- int i, suma = 0, sumc = 0;
- for (i = 0; i < 2*n; ++i)
- {
- if (i < n)
- {
- num[i] = a[i];
- suma += a[i];
- }
- else
- {
- num[i] = c[i-n];
- sumc += c[i-n];
- }
-
- b[i] = false;
- }
- select_combination(0, 0);
- // 下面是追踪交换的顺序
- int ac[n], cc[n], p = 0, q = 0;
- for (i = 0; i < 2*n; ++i)
- {
- if (bc[i])
- ac[p++] = num[i];
- else
- cc[q++] = num[i];
- }
- p = 0;
- int pos;
-
- // 使a中的值与ac中的值相同
- while (p < n)
- {
- if (a[p] == ac[p])
- {
- ++p;
- continue;
- }
- else
- {
- if (find(c, n, ac[p], pos))
- {
- printf("swap %d in a[%d] and %d in c[%d]\n",
- a[p], p, c[pos], pos);
- swap(a[p], c[pos]);
- }
- // a[p] 一定在数组a里 需交换3次
- else
- {
- find(a, n, ac[p], pos);
- printf("swap %d in a[%d] and %d in c[%d]\n",
- a[p], p, c[0], 0);
- swap(a[p], c[0]);
- printf("swap %d in a[%d] and %d in c[%d]\n",
- a[pos], pos, c[0], 0);
- swap(a[pos], c[0]);
- printf("swap %d in a[%d] and %d in c[%d]\n",
- a[p], p, c[0], 0);
- swap(a[p], c[0]);
- }
- }
-
- ++p;
- }
- // 使c中的值与cc中的值相同
- q = 0;
- while (q < n)
- {
- if (c[q] == cc[q])
- {
- ++q;
- continue;
- }
- else
- {
- find(c, n, cc[q], pos);
- printf("swap %d in c[%d] and %d in a[%d]\n",
- c[q], q, a[0], 0);
- swap(c[q], a[0]);
- printf("swap %d in c[%d] and %d in a[%d]\n",
- c[pos], pos, a[0], 0);
- swap(c[pos], a[0]);
- printf("swap %d in c[%d] and %d in a[%d]\n",
- c[q], q, a[0], 0);
- swap(c[p], a[0]);
- }
- ++q;
- }
- printf("\n交换前suma: %d, sumb: %d\n", suma, sumc);
- printf("交换后suma: %d, sumb: %d\n", sumae, sumbe);
- return 0;
- }
复制代码 |
|