子集和问题
Time Limit: 1000 ms Memory Limit: 65536 KiB
子集和问题的一个实例为〈S,t〉。其中,S={ x1 , x2 ,…,xn }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得:
。
试设计一个解子集和问题的回溯法。
对于给定的正整数的集合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 }