描述
子集和问题的一个实例为 (S,C)。其中,S=x1 , x2 , … , xn 是一个正整数的集合,C 是一个正整数。
对于给定的正整数的集合 S,是否存在 S 的一个子集 S1,使得 x∈S1∑x=C
请设计一个求解子集和问题的回溯算法代码。
输入描述
第一行有两个正整数 n 和 C,n 表示 S 的元素个数 (0<n<7000),C 是子集和的目标值。
接下来一行是 n 个正整数,表示集合 S 中的元素。
输出描述
本题可能有多解,输出任意一个即可。子集每个元素后跟一个空格作为分隔。
例:当存在两个解 {2, 2, 6} 和 {6, 4},任意一个均可。当问题无解时,输出 No Solution!
用例输入 1
5 10 2 2 6 5 4
用例输出 1
2 2 6
#include <iostream>
#include<algorithm>
using namespace std;
#define NUM 7010
int vis[NUM]; // 定义一个数组来标记元素是否被选择进入子集
int a[NUM]; // 存储正整数集合S
int n, C;
int flag = 0; // 标记是否找到解
int sum = 0; // 当前子集的和
void dfs(int k){
if(flag){
return;
}
// 如果当前子集的和等于目标值C,则输出解并设置flag为1
if(sum == C){
flag=1;
for(int i=1;i<=n;i++){
if(vis[i]){
printf("%d ",a[i]);
}
}
printf("\n");
}
if(k>n){
return;
}
if(sum+a[k]>C){
return;
}
vis[k]=1; // 将第k个元素加入子集
sum=sum+a[k];
dfs(k+1);
vis[k]=0;
sum=sum-a[k];
dfs(k+1);
}
int main(){
scanf("%d %d",&n,&C);
int t=0;
for (int i=1; i<=n;i++){
scanf("%d",&a[i]) ;
t=t+a[i];
}
if (t<C){
printf("No Solution!\n");
}else{
sort(a+1,a+n+1); //排序
dfs(1); // 从第1个元素开始搜索
// 如果没有找到解
if (!flag){
printf("No Solution!\n");
}
}
return 0;
}