题目1058 部分和问题 简单dfs

部分和问题

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 2
描述
给定整数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 
正确代码
 
   
import java.util.Scanner;
import java.util.Arrays;

public class M {

	static final int MAX = 22;
	static int k, n;
	static int[] a = new int[MAX];
	static int[] b = new int[MAX];//标记数组,便于输出参与计算的a[i]
	 							//最后要输出所有被加的数,随时标记是否要输出这个数字

	// 从左到右遍历一遍可得解 初始化x=0,sun=0 dfs(0,0);到dfs(n,k);
	static boolean dfs(int x, int sum) { 
		if (sum > k)
			return false; // 剪枝,当sum超过k时,也没必要继续搜索
		if (x == n+1)
			return sum == k; // 如果前n项计算过了,返回sum=k是否相等
		//如果前n项没计算,x + 1继续向右搜索
		if (dfs(x + 1, sum)) {
			b[x] = 0;//不加此时的a[x],标记为0;
			return true;
		} 
		if (dfs(x + 1, sum + a[x])) {
			b[x] = 1;// 如果加上a[x]的情况,标记为1;
			return true;
		} 
		else
			return false;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner cin = new Scanner(System.in);

		// 输入
		n = cin.nextInt();
		k = cin.nextInt();
		for (int i = 1; i <= n; i++) {
			a[i] = cin.nextInt();
		}
		
		// 深搜(从最左边开始)
		if (dfs(1, 0)) {
			System.out.println("YES");
			//输出所有参与计算的数字
			for (int i = 1; i <=n; i++)
				//b[i]作为标记
				if (b[i] == 1){
					System.out.print(a[i]);
					if(i<n)
						System.out.print(" ");	
				}	
			System.out.println();
		}
	}
}//
当时遇到的错误:搜索的时候数组索引与输入时的索引不对应



猜你喜欢

转载自blog.csdn.net/dujuancao11/article/details/79656341