題目描述如下:
描述
給定整數a1、a2、…….an,判斷是否可以從中選出若干數,使它們的和恰好爲K。
輸入
首先,n和k,n表示數的個數,k表示數的和。
接着一行n個數。
(1<=n<=20,保證不超int範圍)
輸出
如果和恰好可以爲k,輸出“YES”,並按輸入順序依次輸出是由哪幾個數的和組成,否則“NO”
樣例輸入
4 13
1 2 4 7
樣例輸出
YES
2 4 7
take notes:
解法一:按照全排列的思想,將dfs寫在for循環裏面,先選1 2 4 7,發現超過k要求的數之後回溯,用一個book數組做標記,如果沒有用過的可以用,用過的數只能向下走找到一個沒用過的數,進行運算。這樣寫只能求一種情況,若答案有多種,要用解法二。
import java.util.Scanner;
public class Main {
static int n,k;
static boolean flag = false;
static int[] ans = new int[20];
static int[] book = new int[20];
static void dfs(int x,int sum){
if(sum==k){
flag=true;
return;
}
if(sum>k){
return;
}
else{
for(int i=0;i<n;i++){
if(book[i]==0){
book[i]=1;
dfs(x+1,sum+ans[i]);
if(flag==true)return;
book[i]=0;
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
n=in.nextInt();
k=in.nextInt();
for(int i=0;i<n;i++){
ans[i] = in.nextInt();
}
dfs(0,0);
if(flag==true){
System.out.println("YES");
for(int i=0;i<n;i++){
if(book[i]==1){
System.out.print(ans[i]+" ");
}
}
}
else System.out.println("NO");
}
}
解法二:可以解出多種答案,不需要for循環和book數組,而是需要一個新的數組來存放滿足條件的答案,中心思想就是,當前這個數要還是不要,如果要則應該加在sum中,若不要則減掉,但是無論要還是不要x都要加一,也就是都要往後走,通過存放結果的數組的下表m–來實現回溯,這裏重點要注意,dfs裏面的參數不要動!
import java.util.Scanner;
public class Main {
static int n,k,m;
static int[] ans = new int[20];
static int[] bns = new int[20];
static boolean flag = false;
static void dfs(int x,int sum){
if(sum==k){
System.out.println("YES");
for(int i=0;i<m;i++){
System.out.print(bns[i]+" ");
}
System.out.println();
flag=true;
return;
}
if(sum>k ||x==n){
return;
}
else{
sum=sum+ans[x];
bns[m]=ans[x];
m++;
dfs(x+1,sum);
m--;
sum=sum-ans[x];
dfs(x+1,sum);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
n=in.nextInt();
k=in.nextInt();
for(int i=0;i<n;i++){
ans[i]=in.nextInt();
}
m=0;
dfs(0,0);
if(flag==false)System.out.println("NO");
}
}
分享一組樣例
輸入
4 13
3 10 4 6
輸出
YES
3 10
YES
3 4 6