本人第一次写博客,如有不对,请多加指正。
解法一的思路很明显是错的。。。贪心算法很多情况下求不出最佳解答,因为可能两个数组间需要同时交换两个或者两个以上的数,才能实现差值最小。如{5,5,9,10}{4,7,7,13}
解法二的思路将也就是一个组合的问题在2n个数组中找出n个数,使得n个数之和最接近于sum/2,(这里取小于等于sum/2的情况),时间复杂度指数级。没有按照书本上的思路,自己写了组合代码。
// test_combine.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int MAXSIZE = 8;
int a[] = {4,5,7,9,10,30,20,21};
vector<int> vec;
int result = 0;
int totalSum = 0;
void combineNUM(int num,int index)
{
if (num == 0)
{
int sumv = 0;
for (int i = 0 ; i < vec.size() ; i++)
{
sumv += vec[i];
}
if (sumv > result && sumv <= totalSum/2 )
{
result = sumv;
}
return;
}
if (index == MAXSIZE)
{
return;
}
vec.push_back(a[index]);
combineNUM(num - 1,index + 1);
vec.pop_back();
combineNUM(num,index + 1);
}
void combine()
{
int num = 4 ; //num个数的组合
combineNUM(num,0);
}
int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 0 ; i < MAXSIZE ; i++)
{
totalSum += a[i];
}
combine();
cout << result << endl;
return 0;
}
思路三 个人感觉思路二和思路三的对比就像,斐波那契数列的递归和非递归一样。将已完成的和存起来,供以后使用,来减少时间复杂度。
// test_sum.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
const int MAXSIZE = 100;
int a[] = {4,5,7,9,10,30,20,21};
bool dp[MAXSIZE][MAXSIZE]; //dp dp[i][v]表示是否能找到i个数,使得和为v;
void InitDp()
{
for (int i = 0 ; i < MAXSIZE; i++)
{
for (int j = 0 ; j < MAXSIZE; j++)
{
dp[i][j] = false;
}
}
dp[0][0] = true;
}
void Caculate(int a[],int size,int half_Sum)
{
for (int k = 1; k <= size; k++) //k 代表的是a[]中的下标
{
for (int i = size/2; i >= 1; i-- ) //i代表的是个数
{
for (int v = 1; v <= half_Sum ; v++) //v代表和
{
if (v >= a[k] && dp[i - 1][v - a[k]])
{
dp[i][v] = true;
}
}
}
}
}
int findresult(int a[],int size)
{
int MAX = 0;
for (int i = 0 ; i < MAXSIZE; i++ )
{
if (dp[size/2][i] == true&& i > MAX)
{
MAX = i;
}
}
return MAX;
}
int _tmain(int argc, _TCHAR* argv[])
{
int half_sum = 0;
for (int i = 0 ; i < sizeof(a)/sizeof(int) ; i++)
{
half_sum += a[i];
}
half_sum /= 2;
InitDp();
Caculate(a,sizeof(a)/sizeof(int),half_sum);
cout << findresult(a,sizeof(a)/sizeof(int));
return 0;
}