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]);
			}
		}
	}
}
                    
                
                
            
        
浙公网安备 33010602011771号