子集和问题
给定n个不同的正整数集合w=(w1,w2,…,wn)和一个正数W,要求找出w的子集s,使该子集中所有元素的和为W。
输入格式:
第一行输入n和W,第二行依次输入n个数。
输出格式:
每行输出一个符合要求的子集。
输入样例:
4 31
11 13 24 7
输出样例:
11 13 7
24 7
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(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");
}
}
}