数组分割问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WUDAIJUN/article/details/8700504
// 数组分割.cpp : 定义控制台应用程序的入口点。
//
//问题描述:将一个有2N个元素的数组分为两个元素个数为N的子数组,要求两子数组的和最接近
//思路:《编程之美》P202 用动态规划得到2N个元素中任意N个元素能得到的所有和。再找出其中最接近sum/2的一个 设为x
//		 最后再通过一个动态规划算法找出和为x且个数为N的子数组

#include "stdafx.h"
#include <iostream>
using namespace std;
#include<vector>

int GetHalfSum(int arr[], const int size);
void FindAndPrintSubArr(int arr[], const int size, int AimSum, int curIndex = 0);
int _tmain(int argc, _TCHAR* argv[])
{
	int arr[10] = {1, 5, 7, 8, 9, 6, 3, 11, 20, 17};
	
	int halfsum = GetHalfSum(arr, 10);
	cout<<"halfsum = "<<halfsum<<endl;
	FindAndPrintSubArr(arr, 10, halfsum);
	getchar();
	getchar();
	return 0;
}

int GetHalfSum(int arr[], int size)
{
	//求得原数组元素之和
	int sum = 0;
	for (int i=0; i<size; i++)
		sum += arr[i];

	//求得arr[0...k]中任意i个元素能组成的元素和 随着k增大逐渐扩展 
	//最终将arr中任意i个元素能组成的和保存在vecSumSet[i]中
	vector<vector<int>> vecSumSet(size/2+1);
	vecSumSet.at(0).push_back(0);
	for (int k=0; k<size; k++)
	{
		int i_max = min(k-1, size/2-1);
		for (int i=0; i <= i_max; i++)
		{
			vector<int>::iterator iter = vecSumSet.at(i).begin();
			for( ; iter != vecSumSet.at(i).end(); iter++)
				vecSumSet.at(i+1).push_back(*iter + arr[k]);
		}
	}

	//将vecSumSet[size/2]中的元素取出,逐个与sum/2对比 找出最接近sum/2的size/2个元素的和
	vector<int>::iterator iter = vecSumSet.at(size/2).begin();
	int minDiff = sum;
	int bestSum;
	for (; iter != vecSumSet.at(size/2).end(); iter++)
	{
		int tempDiff = abs(*iter-sum/2);
		if (tempDiff < minDiff)
		{
			minDiff = tempDiff;
			bestSum = *iter;
		}
	}
	return bestSum;
}

//在arr中找出元素个数为size/2且元素和为AimSum的子数组 并输出它和剩余的子数组
void FindAndPrintSubArr(int arr[], const int size, int AimSum, int curIndex)
{
	static vector<int> subArr;
	static int iSchemeNum = 0;

	if (curIndex >= size)
		return;

	//同时满足元素和为AimSum且元素个数为size/2(这里==size/2-1,因为还没算arr[curIndex])
	if (arr[curIndex] == AimSum && subArr.size() == size/2-1)
	{
		subArr.push_back(arr[curIndex]);

		//先输出subArr中的数据
		cout<<"方案 "<<++iSchemeNum<<" : "<<endl;
		vector<int>::iterator iter = subArr.begin();
		for ( ; iter!=subArr.end(); iter++)
			cout<<" "<<*iter;
		cout<<"  \t与    ";

		//输出arr中剩余的数据
		iter = subArr.begin();
		for (int i=0; i<size; i++)
		{
			if (iter == subArr.end() || arr[i] != *iter)
				cout<<" "<<arr[i];
			else
				iter++;
		}
		cout<<endl;
		subArr.pop_back();
	}

	//递归左右子树
	if (arr[curIndex] < AimSum)
	{
		subArr.push_back(arr[curIndex]);
		FindAndPrintSubArr(arr, size, AimSum-arr[curIndex], curIndex+1);
		subArr.pop_back();
	}
	FindAndPrintSubArr(arr, size, AimSum, curIndex+1);
}

猜你喜欢

转载自blog.csdn.net/WUDAIJUN/article/details/8700504