数组分割

将大小为2N的数组分成两个大小为N的数组,使得两个子数组之和最接近

#include<iostream>

using namespace std;

#define min(a,b) (((a)<=(b))?(a):(b))

void function(int arr[],int n)

{

int sum=0;

int i;

int rem;

int **isOK;

int k;

int v;

for (i=1;i<=2*n;i++)

{

sum += arr[i];

}

rem=sum/2;

isOK=(int **)malloc(sizeof(int*)*(n+3));

for (i=0;i<=n+1;i++)

{

isOK[i]=(int *)malloc(sizeof(int)*(sum+2));

memset(isOK[i],0,sizeof(isOK[i])*(sum+2));//动态分配内存之后初始化。

}

isOK[0][0]=1;

for (k=1;k<=2*n;k++)

{//对于前K个数的情况

for (i=1;i=min(k,n);i++)

//这里FOR循环I必须是递增,不能是递减,因为否则下面的isOK[i-1][v-arr[k]]会导致某个i会在前一个i-1中继续加上arr[k],导致arr[k]被使用两次

{

//这一层循环的目的在于对于正在考虑的元素arr[k],它加入进来后,该子集的个数是不确定的,因此需要逐步遍历考虑。可能前k个全部加入,也可能只是1和k两个元素。

//从前K个数里面,选择i个数。当k>n时,表示考虑到了后面n个,但是最多只能取n个。这里考虑的是从2n中取出n个,并且使得这n个之和最接近sum/2

for (v=1;v<=rem;v++)

{

if (v>=arr[k]&&(isOK[i-1][v-arr[k]]))

//这里的i表示有多少个元素

当前只考虑是否把第k个元素是否加入进来

{

isOK[i][v]=1;

}

}

}

}

v=rem;

while (v>=1&&(!isOK[n][v]))

{

v--;

}

cout<<"两个数组的差为:"<<sum-2*v<<endl;

}

int main()

{

int n;

int *arr;

int i;

cout<<"请输入 n : ";

cin>>n;

arr=(int *)malloc(sizeof(int)*(n+2));

cout<<"请输入 "<<2*n<<"个数字:"<<endl;

for (i=1;i<=2*n;i++)

{

cin>>arr[i];

}

function(arr,n);

return 0;

}

时间: 2024-09-30 06:37:01

数组分割的相关文章

【编程之美】数组分割

有一个无序.元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组的和最接近? 分析与解法 从题目中可以分析出,题目的本质就是要从2n个整数中找出n个,使得它们的和尽可能地靠近所有整数之和的一半. 解法一:不靠谱的解法 先将数组的所有元素排序,然后划分为S1 = {a1, a3, ..., a2n-1}和S2 = {a2, a4, ..., a2n}: 从S1和S2中找出一对数进行交换,使得两个集合中所有元素的和之间的差值尽可能的小,直到找不到可对换的.

数组分割问题(转)

题记:这道题和<编程之美>一书中2.18节的数组分割区别不大,但本人觉得<编程之美>这一节讲的不够透彻,不好理解(或许本人愚钝),故给出自己的思路,同时也给出打印其中一种方案的方法(这一点<编程之美>并没有提到). 两个序列大小均为n,序列元素的值为任一整数,无序: 要求通过交换两个序列的元素,使序列a元素之和与序列b的元素之和的差最小(可能存在很多种组合,要求找出其中一种即可). 如序列:1  5   7   8   9和序列6  3   11  20  17我们可以

数组分割问题

昨天同学问我一道关于数组分割的问题——有一个无序.元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并是两个子数组的和最接近. 假设2n个整数之和为sum.从2n个整数中找出n个元素的和,有三种可能:大于sum/2,等于sum/2,小于sum/2.可以考虑小于等于sum/2的情况.使用动态规划解决这个问题,其实这是一个NP问题,只能尽量去接近sum/2这个值. 我们可以定义dp[k][s]代表从前k个数中去任意个元素,且k小于等于n,其和为s是否存在:之所以将选出的

数组分割问题(转载)

问题: 1. 有一个无序.元素个数为2n的正整数数组,要求:如何能把这个数组分割为两个子数组,子数组的元素个数不限,并使两个子数组之和最接近. 2. 有一个无序.元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组之和最接近. 分析: 假设数组A[1..2N]所有元素的和是SUM.模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合.显然:                S(k, 1) = {A[i] | 1<= i

[经典面试题][网易]数组分割

[题目] 任意2N个正整数,从其中选出N个整数,使得选出的N个整数和同剩下的N个整数之和的差最小. [来源] 网易 [分析] 假设数组A[1..2N]所有元素的和是SUM.模仿动态规划解0-1背包问题的策略. 从2N个数中找N个元素,有三种可能:大于Sum/2,小于Sum/2以及等于Sum/2.而大于Sum/2与小于等于Sum/2没区别,故可以只考虑小于等于Sum/2的情况. 令S(k, i)表示前k个元素中任意i个元素的和的集合.显然: S(k, 1) = {A[i] | 1<= i <=

数组分割——解题笔记

数组分割--解题笔记 题目:有一个没有排序.元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组的和最接近. 分析:这道题目可以用动态规划求解,或者说是一个典型的0,1背包问题,对于第i的数,到底是放进去还是不放,就要看放了对结果有什么影响,不放对结果又有什么影响.而结果是依据题目而言的,这道题目中的结果就是数组之和. 注意,一般动态规划数组中,需要先初始化所有i的结果,初始化可以为1,或者0. 然后,从前往后,依次得到每个i的优化结果,而且需要注意的是

编程之美2.18 数组分割 原创解O(nlogn)的时间复杂度求解:

题目:有一个无序.元素个数为2n的正整数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组的和最接近? 1 1 2 -> 1 1 vs  2 看题时,解法的时间复杂度一般都大于或等于O(n^2).突然灵感一闪,发现一个新的解法,应该算是一个动态规划的过程吧,思路比较简单,请看代码.空间复杂度O(nlogn),时间复杂度O(n).但是不能确定是否适用所有正整数组,如果有错,请给出你的测试用例,谢谢! 代码如下: 1 1 #include <iostream> 2 2 #

算法之--数组分割

题目来源:编程之美2.18 有一个无序的,元素个数为2n的正整数的数组,要求: 如何能把这个数组分割为元素个数为n的两个数组,使得两个子数组的和尽量接近. 解析:因为两个子数组的和是一定的,等于整个数组的和.现在要求使得两个字数组的和尽量的接近,也就意味着要从其中选出n个数使得这n个数的和尽可能的接近sum/2,不妨设为从小于sum/2的方向接近.于是,这就是一个01背包的问题: 现在有2N个物品,每个物品的重量为A[i],有一个背包的大小为sum/2,现在从中挑选出N个物品,使得背包尽可能的被

编程之美2.18—数组分割

题目: 有一个没有排序,元素个数为2N的正整数数组.要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近. 基本思想: 假设数组A[1..2N]所有元素的和是SUM.模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合. 显然: S(k, 1) = {A[i] | 1<= i <= k} S(k, k) = {A[1]+A[2]+-+A[k]} S(k, i) = S(k-1, i) U {A[k] + x | x属于S(k-1, i-1) }

编程之美——数组分割

一.题目概述:有一个没有排序,元素个数为2N的正整数数组.要求把它分割为元素个数为N的两个数组,并使两个子数组的和最接近.假设数组A[1..2N]所有元素的和是SUM.模仿动态规划解0-1背包问题的策略,令S(k, i)表示前k个元素中任意i个元素的和的集合.显然:S(k, 1) = {A[i] | 1<= i <= k}S(k, k) = {A[1]+A[2]+…+A[k]}S(k, i) = S(k-1, i) U {A[k] + x | x属于S(k-1, i-1) }按照这个递推公式来