Description
子集和问题的一个实例为 ( S, c )。其中,S={ x1 ,x2 ,…,xn }是一个正整数的集合,c是一个正整数。
对于给定的正整数的集合S,是否存在S的一个子集S1之和等于c 。试设计一个解子集和问题的回溯法。
Input
输入第一行有两个正整数n 和c,n 表示S的大小( 0 < n < 7000 ),c是子集和的目标值。接下来的一行,有n个正整数,表示集合S中的元素。
Output
本题有多解,请输出满足条件的、按升序排列最小的子集。
如:存在两个解:2 2 6 和 6 4,则输出2 2 6这个解。当问题无解时,输出 “No Solution!”
Sample Input
5 10
2 2 6 5 4
Sample Output
2 2 6
C/C++_code
///离亭晚2020.11.16.00.00.51
#include<bits/stdc++.h>
using namespace std;
bool finds,used[7002];
int n,c,sum;
int len=0;
int a[7002],b[7002];
void DFS(int i)
{
if(sum==c){
finds=true; //标记已找到ans
for(int t=1;t<=n;t++){
if(used[t]==true)
printf("%d ",a[t]);
}
printf("\n");
return ;
}
if(finds==true) return; //finds==true,即刻退出DFS
if(i>n) return ; //i从始 (1...n),保证递归层数不超过 n
if(sum+b[i]<c) return ; //当前sum加后缀和仍小于c,继续DFS也不能使sum==c
if(a[i]+sum>c){ //跳过i,对i+1进行DFS
DFS(i+1);
return ;
}
sum+=a[i];
used[i]=true;
DFS(i+1);
sum-=a[i];
used[i]=false;
DFS(i+1);
return ;
}
int main()
{
scanf("%d %d",&n,&c);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
used[i]=false;
}
sort(a,a+n+1);
b[n]=a[n];
for(int i=n-1;i>0;i--)//b[]存后缀和
b[i]=a[i]+b[i+1];
DFS(1);
if(finds==false)
printf("No Solution!\n");
return 0;
}