子集和问题
问题描述:给定集合S,S中有n个正整数,M是一个正整数。子集和问题判定是否存在S的一个子集S1,使得S1中各元素之和等于M。
请设计回溯法求解子集和问题,
如果问题无解,输出“No Solution”
问题有解,则输出满足子集S1中各元素的值。
import java.io.*;
@SuppressWarnings("all")
public class subset_sum_problem {//子集和问题--回溯法
static int sum = 0;
static boolean flag;//默认为false
//当前起点序号 子集总数 要求的数 子集集合 判断该数是否被加上true为该数已经被加上
private static void dfs(int i,int n,int W,int []s,boolean []vis){
if(sum > W || i == n) {//表示下一个要求的子集已经超出范围 或者 当前的子集和已经超过了要求的数
return;
}
vis[i] = true;//表示该子集已经被加上
sum += s[i];//遍历
if(sum == W) {//表示当前子集和等于要求的 W
for(int j = 0;j <= i;j++) {//依次输出
if(vis[j] == true) {
System.out.print(s[j] + " ");
}
}
flag = true;
System.out.println();
}
else if(sum < W) {//当前子集和小于要求的 W
dfs(i + 1,n,W,s,vis);
}
vis[i] = false;//剪枝
sum -= s[i];//剪枝
dfs(i + 1,n,W,s,vis);//将当前位置向后移动
return;
}
public static void main(String args[]) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));//输入流耗时更短
String []s = reader.readLine().split(" ");
int n = Integer.parseInt(s[0]);//n个整数
int W = Integer.parseInt(s[1]);//要求的数
int []S = new int[n];//w的子集
s = reader.readLine().split(" ");
for(int i = 0;i < n;i++) {
S[i] = Integer.parseInt(s[i]);
}
boolean []vis = new boolean[n];
dfs(0,n,W,S,vis);
if(!flag) {//当没有路线,没有子集和等于W时,输出No Solution;
System.out.println("No Solution");
}
}
}