POJ 3977 Subset

探讨了如何通过折半搜索算法解决子集和绝对值最小的问题,利用C++实现并考虑子集元素数量最少的情况。

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

Description

Given a list of N integers with absolute values no larger than 10 15, find a non empty subset of these numbers which minimizes the absolute value of the sum of its elements. In case there are multiple subsets, choose the one with fewer elements.

题意是给定n个数字,要求找到其一个非空子集,使得这个子集内绝对值的和最小。

类似的题目,由于很多数根本不会出现,而且数字非常大,一般来说都是折半搜索,先扫一边,在另一边用stl里的map查询有无,但是或许是因为自己写挫了的缘故,超时了。

所以最后我选择了用数组模拟,由于还有统计最少需要多少个,故开了一个结构体,v表示它的和,cnt表示构成它所需的次数,使用折半搜索的思想,折半先构造出前一半所能达到的和。接着构造后一半能达到的和sum,查找-sum是否能在前一半种找到,找不到就找最贴近的那一个。这时问题转换成了如何查找所有数内,与某个数最贴近的数,幸好c++算法库里自带lower_bound函数,算以我们可以在算出前一半时排序,在算后一半时边算达到的和sum,边查找-sum,由于最贴近的那一个如果-sum不存在,那就是大于-sum最小的值了,而需要的是绝对值,所以我们还要将这是lower_bound算出的pos-1,来求出小于-sum最大的值。注意lower_bound如果查不到返回的是右端点的值,所以如果这时pos如果是右端点,就给它-1,还要保证在求小于-sum最大的值时,pos-1是>0的。

下附AC代码

#include<iostream>
#include<algorithm>
#define maxn 40
using namespace std;
typedef long long ll ;
int n;
ll myabs(ll i)
{
	return i>=0 ? i : -i;
}
struct nod
{
	ll v;
	int cnt;
	nod(ll a,int b)
	{
		v=a;
		cnt=b;
	}
	nod(){}
}a[1<<20];
ll num[maxn];
bool operator <(nod i,nod j)
{
	if(i.v!=j.v)
	return i.v<j.v;
	return i.cnt<j.cnt;
}
int main()
{
	while(cin>>n && n)
	{
		ll cnt1=0,cnt2=0;
		for(int i=0;i<n;i++)
		cin>>num[i];
		
		nod ans=nod(myabs(num[0]),1);
		
		int mid=n>>1;
		
		for(ll i=0;i<(1<<mid);i++)
		{
			int ncnt=0;
			a[i].v=0;
			for(int j=0;j<mid;j++)
			if((i>>j) & 1)
			{
				a[i].v+=num[j];
				ncnt++;
			}
			a[i].cnt=ncnt;
			if(i)
			ans=min(ans,nod(myabs(a[i].v),a[i].cnt));
		}
		
		sort(a,a+(1<<mid));
		
		for(ll i=0;i<(1<<mid)-1;i++)
		if(a[i].v==a[i+1].v)
		{
			a[i+1].cnt=a[i].cnt;
		} 
		for(ll i=1;i<(1<<(n-mid));i++)
		{
			ll nsum=0;
			int ncnt=0;
			for(int j=0;j<n-mid;j++)
			if((i>>j) & 1)
			{
				nsum+=num[mid+j];
				ncnt++;
			}

			nod now=nod(myabs(nsum),ncnt);
			ans=min(ans,now);
			
			ll pos=lower_bound(a,a+(1<<mid),nod(-nsum,0))-a;
			for(int j=min(pos,(long long)((1<<mid)-1));j>=max(pos-1,0ll);j--)
			{
				ans=min(ans,nod(myabs(a[j].v+nsum),a[j].cnt+ncnt)); 
			}
		}
		cout<<ans.v<<' '<<ans.cnt<<endl;
	}
}


Rebuild started: Project: Project *** Using Compiler &#39;V6.22&#39;, folder: &#39;E:\Keil_v5\ARM\ARMCLANG\Bin&#39; Rebuild target &#39;Target 1&#39; assembling startup_stm32f10x_md.s... Start/core_cm3.c(445): error: non-ASM statement in naked function is not supported 445 | uint32_t result=0; | ^ Start/core_cm3.c(442): note: attribute is here 442 | uint32_t __get_PSP(void) __attribute__( ( naked ) ); | ^ Start/core_cm3.c(465): error: parameter references not allowed in naked functions 465 | "BX lr \n\t" : : "r" (topOfProcStack) ); | ^ Start/core_cm3.c(461): note: attribute is here 461 | void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) ); | ^ Start/core_cm3.c(479): error: non-ASM statement in naked function is not supported 479 | uint32_t result=0; | ^ Start/core_cm3.c(476): note: attribute is here 476 | uint32_t __get_MSP(void) __attribute__( ( naked ) ); | ^ Start/core_cm3.c(499): error: parameter references not allowed in naked functions 499 | "BX lr \n\t" : : "r" (topOfMainStack) ); | ^ Start/core_cm3.c(495): note: attribute is here 495 | void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) ); | ^ 4 errors generated. compiling core_cm3.c... compiling misc.c... compiling system_stm32f10x.c... compiling stm32f10x_adc.c... compiling stm32f10x_dac.c... compiling stm32f10x_exti.c... compiling stm32f10x_dbgmcu.c... compiling stm32f10x_dma.c... compiling stm32f10x_crc.c... compiling stm32f10x_cec.c... compiling stm32f10x_bkp.c... compiling stm32f10x_can.c... compiling stm32f10x_flash.c... compiling stm32f10x_pwr.c... compiling stm32f10x_fsmc.c... compiling stm32f10x_
03-31
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值