《编程之美》数组分割

本文详细介绍了如何使用暴力法解决数组分割问题,通过枚举所有可能的组合来找到和最接近一半的子集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《编程之美》——2.18数组分割

题目的意思大概是这样的: 一个数组的长度为2N,要求将数组分割成长度相同的两个序列,要求两个序列的和尽可能的接近!!或者说从中选出N个使他们的和最接近原来和的一半。


书中piapia~~~~!讲了很多~~~!!可是我没看懂!!!

我只能用最暴力的方法做了!

暴力的方法:2N个数中选取N个的所有情况,是不是就是N个0,和N个1的全排列;

比如N=2;我们假设1,0分别表示这个位置上的数被选入不同数组

那么所有情况为

0 0 1 1

0 1 0 1

0 1 1 0

1 0 0 1

1 0 1 0

1 1 0 0

好吧情况有点多!!!既然穷举法了,干脆一不做二不休,全排列也不自己写了!!!

用库函数next_premutation求全排列,先把选择设定为非减(字典序最小),不停调用这个函数,直到选择非增(字典序最大)!!记录每一种情况

#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
int arr[]={1,5,7,8,9,6,3,11,20,17};
const int N=sizeof(arr)/sizeof(int);
int CurSelect[N];//当前的选择,0表示不选这个数,1表示选取这个数
int FinalSelect[N];//最后的选择结果
int sum()
{
	int sum=0;
	//计算当前数组的和
	for(int i=0;i<N;i++)
		if(CurSelect[i])
			sum+=arr[i];
	return sum;
}
int main(int argc,char* argv[])
{
	//计算数组和的一半
	int halfSum=0;
	for(int i=0;i<N;i++)
		halfSum+=arr[i];
	halfSum/=2;
	//初始化选择为最小的字典序(非减序列)
	for(int i=0;i<N;i++)
		CurSelect[i]=FinalSelect[i]=0;
	for(int i=N-1;i>=N/2;i--)
		CurSelect[i]=FinalSelect[i]=1;
	int AnsSum=sum();
	AnsSum=AnsSum>halfSum?AnsSum-halfSum:halfSum-AnsSum;
	int tmp;
	while(next_permutation(CurSelect,CurSelect+N)&&AnsSum!=0)//全排列
	{
		tmp=sum();
		tmp=tmp>halfSum?tmp-halfSum:halfSum-tmp;
		if(tmp<AnsSum)
		{
			for(int i=0;i<N;i++)
				FinalSelect[i]=CurSelect[i];
			AnsSum=tmp;
		}
	}
	AnsSum=0;
	int allsum=0;
	for(int i=0;i<N;i++)
	{
		allsum+=arr[i];
		if(FinalSelect[i])
		{
			AnsSum+=arr[i];
			cout<<arr[i]<<"  ";
		}
	}
	cout<<endl;
	cout<<"All Sum : "<<allsum<<endl;
	cout<<"S1 Sum : "<<AnsSum<<endl;
	system("pause");
	return 0;
}

看到这里是不是觉的这个博主太特么水了~~~~!穷举法也好意思拿上来骗人?!
~~~!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值