题目:
有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小。
例如:
var a = [100,99,98,1,2, 3];
var b = [1, 2, 3, 4,5,40];
最后的结果为:
var a = [1,99,98,1,2,2];
var b = [100, 3,3,4,5,40];
思路一:
首先先计算a,b中元素和之间的差绝对值ABDis,然后逐一的把a中的元素和b中的任一元素作比较,如果它们交换后的差值绝对值ABTempDis小于原来的值ABDis,那么就把a,b交换,并重新计算a和b的绝对值,这种动作反复的进行,直到a中任一的元素都不能和b中的任一元素交换为止。(其实是穷举法)
代码如下:
/*-------------------------------
Copyright by yuucyf. 2011.08.19
--------------------------------*/
#include "stdafx.h"
#include
#include
using namespace std;
__int64 MakeSmallly(int *pA, int i32ALen, int *pB, int i32BLen)
{
assert(pA);
assert(pB);
assert(i32ALen > 0);
assert(i32BLen > 0);
int i32I = 0, i32J = 0, i32Temp = 0;
__int64 i64ASum = 0, i64BSum = 0;
__int64 i64ABDis = 0, i64TempDis = 0;
for (i32I = 0; i32I < i32ALen; i32I++)
i64ASum += pA[i32I];
for (i32I = 0; i32I < i32BLen; i32I++)
i64BSum += pB[i32I];
i64ABDis = _abs64(i64ASum - i64BSum);
bool bSwap = false;
for (i32I = 0; i32I < i32ALen; i32I++)
{
while (true)
{
for (i32J = 0; i32J < i32BLen; i32J++)
{
i64TempDis = _abs64((i64ASum - pA[i32I] + pB[i32J]) -
(i64BSum - pB[i32J] + pA[i32I]));
if (i64TempDis < i64ABDis)
{
i64ASum += (pB[i32J] - pA[i32I]);
i64BSum += (pA[i32I] - pB[i32J]);
i64ABDis = i64TempDis;
i32Temp = pA[i32I];
pA[i32I] = pB[i32J];
pB[i32J] = i32Temp;
bSwap = true;
break;
}
}
if (i32J >= i32BLen)
break;
}
//如果有交换,且i32ALen的值为最后一个元素,
//那么我们必须重新再来一遍,直到没有元素交换为止.
if ((i32I == i32ALen - 1) && bSwap)
{
bSwap = false;
i32I = -1;
}
}
return i64ABDis;
}
int _tmain(int argc, _TCHAR* argv[])
{
int aryA[] = {100, 99, 98, 1, 2, 3};
int aryB[] = {1, 2, 3, 4, 5, 40};
__int64 i64Dis = MakeSmallly(aryA, sizeof(aryA)/sizeof(aryA[0]), aryB, sizeof(aryB)/sizeof(aryB[0]));
cout << "A,B系列元素的最小差为:" << i64Dis << ",最后的结果为,A系列元素为";
for (int i32I = 0; i32I < sizeof(aryA)/sizeof(aryA[0]); i32I++)
cout << aryA[i32I] << " ";
cout << ",B系列元素为";
for (int i32I = 0; i32I < sizeof(aryB)/sizeof(aryB[0]); i32I++)
cout << aryB[i32I] << " ";
cout << endl;
return 0;
}
思路二:
当前数组a和数组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])
设x = a[i] - b[j],那么
A' = |A - 2x|,当然A' 越小也好,所以当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好,如果找不到在(0,A)之间的x,则当前的a和b就是答案。
所以算法大概如下:在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。
代码和思路给出的代码差不多,这里就不给出代码了。