7-1 子集和問題 (50 分)

設集合S={x1,x2,…,xn}是一個正整數集合,c是一個正整數,子集和問題斷定是否存在S的一個子集S1,使S1中的元素之和爲c。試設計一個解子集和問題的回溯法。java

輸入格式:

輸入數據第1行有2個正整數n和c,n表示S的大小,c是子集和的目標值。接下來的1行中,有n個正整數,表示集合S中的元素。 是子集和的目標值。接下來的1 行中,有n個正整數,表示集合S中的元素。算法

輸出格式:

輸出子集和問題的解,以空格分隔,最後一個輸出的後面有空格。當問題無解時,輸出「No Solution!」。設計

輸入樣例:

在這裏給出一組輸入。例如:code

5 10
2 2 6 5 4

輸出樣例:

在這裏給出相應的輸出。例如:遞歸

2 2 6 

 

本題要求只輸出第一個解,並採用回溯法,因此能夠主體來枚舉全部狀況,而後再剪枝剪掉不須要的分支:io


package 宿題;
import java.io.*;

public class PTASubsetSum {
static int c;
static int n;
static boolean Out=true;//這裏新建一個標記位,用來記錄有無第一個解出現,結束遞歸;
public static void main(String args[])throws IOException{
  StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));//當須要輸入大量數據時BufferedReader處理速度快,比Scanner高效;
  in.nextToken();
  n=(int)in.nval;
  in.nextToken();
  c=(int)in.nval;
  int a[]=new int[n];
  int SUM=0;
  for(int i=0;i<n;i++){
    in.nextToken();
    a[i]=(int)in.nval;
    SUM+=a[i];//減去當全部數和小於c時的分支;
  }
  if(SUM>=c){
    Count(a,0,0,"");
    if(Out)
      System.out.println("No Solution!");
  }else
    System.out.println("No Solution!");
  }

  private static void Count(int a[],int count,int sum,String s){
    if(count<n&&Out){
      if(sum+a[count]==c){
        Out=false;//結束遞歸;
        System.out.println(s+a[count]+" ");
      }else if(sum+a[count]<c){//分支向下求解;
        Count(a,count+1,sum+a[count],s+a[count]+" ");
        System.out.println(s+a[count]+" ");
      }
      Count(a,count+1,sum,s);
      System.out.println(s);
    }
  }

}class

 

該算法最壞情形下時間複雜度爲O(2^n)。import

相關文章
相關標籤/搜索