子集和问题

子集和问题

Description

子集和问题的一个实例为〈S,t〉。其中,S={ x1 , x2 ,…,xn }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得:子集S1和等于c。
试设计一个解子集和问题的回溯法。
对于给定的正整数的集合S={ x1 , x2 ,…,xn }和正整数c,计算S 的一个子集S1,使得:子集S1和等于c。

Input

输入数据的第1 行有2 个正整数n 和c(n≤10000,c≤10000000),n 表示S 的大小,c是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。
Output
将子集和问题的解输出。当问题无解时,输出“No Solution!”。

Samples
Sample #1
Input
5 10
2 2 6 5 4
Output
2 2 6

分析:

深度搜索

#include
#include
using namespace std;
typedef long long ll;

int n, c,t;
int s[1000005]; //逐一枚举最大是N*logS
int sum=0;
int flag[1000005]={0};//标记加入子集的数 
int x=0;
void dfs(int t){
	if(x==1)//已存在所需子集 
		return;
	if(t==n){//遍历至最后一个数 
		if(sum==c){//和目标值相同,即存在所需子集 
			x=1;
			for(int i=0;i<n;i++){
				if(flag[i])
				    cout<<s[i]<<" ";   
			}
		}
		return ;
	}
	if(sum>c)//大于目标数,返回上一节点,遍历下一条路 
	    return;
	flag[t]=1;//加入子集 
	sum+=s[t];
	dfs(t+1);//遍历下一个数 
	flag[t]=0;//该点指向的的路都遍历完了,从子集中去掉 
	sum-=s[t];
	dfs(t+1);
}
int main()
{
	cin>>n>>c;
	int u=0;
	for(int i=0;i<n;i++){
		cin>>s[i];
		u+=s[i];
	}
	if(u<c)//直接算所有数的和是否小于目标值,去掉的话,时间复杂度会超 
	   cout<<"No Solution!";
	else{
		dfs(0);   //深度搜索 
	    if(x==0)
	        cout<<"No Solution!";
	   }
	
    return 0;
}

你可能感兴趣的:(题解,算法,深度优先,图论,c++)