7-16 子集和问题
设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法。
输入格式:
输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。 是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。
输出格式:
输出子集和问题的解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。
输入样例:
在这里给出一组输入。例如:
5 10
2 2 6 5 4
输出样例:
在这里给出相应的输出。例如:
2 2 6
思路:本题采用回溯法来实现查找满足条件的子集和, 因为是只输出一个结果所以在找到满足一个条件之后就退出查找。
import java.util.Scanner;
public class Main {
public static int n;
public static int m;
public static int a[];
public static int ans[];
public static int count=0;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//the length of s
n = in.nextInt();
//the size of target
m = in.nextInt();
a = new int[n];
ans = new int[n];
for(int i=0;i<n;i++){
a[i] = in.nextInt();
}
dfs(0, 0, Rm());
if(count==0){
System.out.println("No Solution!");
}
}
public static int Rm(){
int rm=0;
for(int i=0;i<n;i++){
rm+=a[i];
}
return rm;
}
public static void dfs(int i, int sum, int rm){
if(i>=n){
if(sum==m&&count==0){
for(int k=0;k<n;k++){
if(ans[k]==1){
System.out.print(a[k]+" ");
}
}
count++;
System.exit(0);//找到一个结果之后强制退出,否则在pta提交会出现一个测试点超时
}
}else{
if(sum+a[i]<=m){
ans[i] = 1;
dfs(i+1,sum+a[i],rm-a[i]);
}
if(sum+rm-a[i]>=m){
ans[i] = 0;
dfs(i+1, sum, rm-a[i]);
}
}
}
}