子集和问题

Time Limit: 1000 ms Memory Limit: 65536 KiB
子集和问题的一个实例为〈S,t〉。其中,S={  x1 , x2 ,…,xn }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得:

试设计一个解子集和问题的回溯法。
对于给定的正整数的集合S={  x1 , x2 ,…,xn }和正整数c,计算S 的一个子集S1,使得:

Input

输入数据的第1 行有2 个正整数n 和c(n≤10000,c≤10000000),n 表示S 的大小,c是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。

Output

将子集和问题的解输出。当问题无解时,输出“No Solution!”。

Sample Input

5 10
2 2 6 5 4

Sample Output

2 2 6

Hint

Source

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n,c;
 4 int data[10001];
 5 int ans[10001];
 6 bool flag=false;
 7 int sum,k;
 8 void dfs(int i){
 9     if(flag) return ;//找到了一个   就可以直接返回了
10     sum+=data[i];//还未找到,继续 加
11     ans[k++]=data[i];//存上 这个 数据
12     if(sum>c) return ;//sum 超过要找的c   剪枝
13     if(sum==c) { flag=true; return ;}//找到结果,返回
14     for(int j=i+1;j<=n;j++){// 直接传(i+1) 不对
15         dfs(j);//继续遍历下面的数据
16         if(!flag){//sum!=c 的时候 ,不满足,回溯,恢复数据
17             sum-=data[j];//总和减去 这个数据   这里容易写错  是j不是 i
18             k--;//存答案的数据 要 减去 这个不满足的数据
19         }
20     }
21 }
22 int main()
23 {
24     cin>>n>>c;
25     int tmpSum=0;//如果 不写这个 与判断的 ,可能 这个数据很大,浪费时间 超时
26     sum=0,k=0;
27     for(int i=0;i<n;i++){
28         cin>>data[i];
29         tmpSum+=data[i];
30     }
31     if(tmpSum<c){// 预判 全部的 数据和 是否能达到 要求的c
32         cout<<"No Solution!"<<endl;
33         return 0;
34     }
35     dfs(0);//开始搜索
36     if(flag){//找到一个 结果
37         for(int i=0;i<k;i++){//遍历输出
38             cout<<ans[i];
39             if(i!=k-1)
40                 cout<<" ";
41         }
42         cout<<endl;//加不加都对
43     }else cout<<"No Solution!"<<endl;
44     return 0;
45 }
01-08 14:25