ACM —— 1011 Sticks

解题代码:


import java.util.Arrays;
import java.util.Scanner;

public class Main {

	static int num;
	static int[] sticks;
	static boolean[] vists;
	public static void main(String[] args) {
		Scanner stdin = new Scanner(System.in);
		int maxLen;
		int sumLen;
		while ((num = stdin.nextInt()) != 0) {
			sticks = new int[num];
			vists = new boolean[num];
			sumLen = 0;
			for (int i = 0; i < num; i++) {
				sticks[i] = stdin.nextInt();
				sumLen += sticks[i];
			}
			Arrays.sort(sticks);
			maxLen = sticks[num - 1];
			boolean flag = false;
			for (int l = maxLen; l <= sumLen - maxLen; l++) { //剪枝1,若能在[maxlen,sumlen-InitLen]找到最短的l,该l必也是[maxlen,sumlen]的最短
				//剪枝2,InitLen必是sumlen的约数
				if ((sumLen%l == 0)&&dfs(0, l, num - 1, 0)) {
					System.out.println(l);
					flag = true;
				}
			}
			if(!flag) {
				System.out.println(sumLen);
			}
		}
		
	}

	private static boolean dfs(int len, int l,
			int s, int n) {
		if (n == num) {
			return true;
		}
		int sample = -1;
		for (int i = s; i >= 0; i--) {
			if(vists[i] || sticks[i]==sample) { //剪枝3,等长的木棒只搜索一次 
				continue; 
			}
			
			vists[i] = true;
			if (len + sticks[i] == l) {
				if (dfs(0, l, num - 1, n + 1)) {
					return true;
				} else {
					sample = sticks[i];
				}
			} else if (len + sticks[i] < l) {
				if (dfs(len + sticks[i], l, i, n+1)) {
					return true;
				} else {
					sample = sticks[i];
				}
			}
			vists[i] = false;
			
			if (len == 0) {//剪枝4,构建新棒时,对于新棒的第一根棒子,在搜索完所有棒子后都无法组合   
			//则说明该棒子无法在当前组合方式下组合,不用往下搜索(往下搜索会令该棒子被舍弃),直接返回上一层 
				break;
			}
		}
		return false;
	}
}

DFS + 剪枝

猜你喜欢

转载自blog.csdn.net/WYYZ5/article/details/48628731