每天学习一算法系列(29)(有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小)

题目:

有两个序列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为止。

代码和思路给出的代码差不多,这里就不给出代码了。

 


 

你可能感兴趣的:(数据结构/算法)