牛客网多校 D Knapsack Cryptosystem(折半搜索)

题意:

给出一个集合,和一个数num,试求集合中的sum是否等于num,若是则输出路径(0表示没在用,1表示有在用),确保有且仅有一个正解

 

思路:

1.折半搜索

2.用map来hash,储存h[cnt]=string(表示当前半段组成的数字cnt的路径为什么),那么只需要暴力出前半个集合的所有可能性,然后搜索后半段,在收索后半段的时候,当我们当前后半段的值为ans,那么我们只需要判断hash[num-ans]是否出现即可,若是则把两边的路径合并输出即可

 

#include <stdio.h>
#include<string>
#include<algorithm>
#include <map>
#include<iostream>
using namespace std;
typedef long long ll;
ll n,num;

map<ll,bool>S; 
map<ll,string>all;
ll a[101];
int index,index2;
void dfs(ll ans,string path,int cnt)
{
	if(cnt==n/2&&S[ans]==false)
	{
		S[ans]=true;
		all[ans]=path;
		return ;	
	}	
	dfs(ans+a[cnt],path+"1",cnt+1);
	dfs(ans,path+"0",cnt+1);	
}
void dfs2(ll ans,string path,int cnt)
{

	if(cnt==n)
	{	
		if(S[num-ans]==true)
		{	
		
			cout<<all[num-ans]<<path<<endl;	
		}
		return ;	
	}	
	dfs2(ans+a[cnt],path+"1",cnt+1);	
	dfs2(ans,path+"0",cnt+1);
}
int main(int argc, char *argv[])
{
	while(scanf("%lld %lld",&n,&num)!=EOF)
	{
		int i;
		for(i=0;i<n;i++)
		{
			scanf("%lld",&a[i]);
		}
		S.clear();
		dfs(0,"",0);			
		dfs2(0,"",n/2);
	}		
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值