http://poj.org/problem?id=1011&lang=default&change=true
1 import java.io.BufferedReader; 2 import java.io.InputStreamReader; 3 import java.util.Arrays; 4 import java.util.StringTokenizer; 5 6 public class Main { 7 static boolean[] used; 8 static int len; 9 static int[] s; 10 static int sum; 11 static int max; 12 static int parts; 13 14 public static void main(String[] args) throws Exception { 15 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 16 while ((len = Integer.parseInt(reader.readLine())) != 0) { 17 s = new int[len]; 18 StringTokenizer take = new StringTokenizer(reader.readLine()); 19 int index = 0; 20 used = new boolean[len]; 21 sum = 0; 22 while (take.hasMoreTokens()) { 23 s[index] = Integer.parseInt(take.nextToken()); 24 sum += s[index++]; 25 } 26 //对木棍长度进行排序 27 Arrays.sort(s); 28 max = s[len - 1]; 29 30 //木棒长度肯定是大于木棍长度的,必然从最长的开始进行合并 31 for (; max <= sum; max++) { 32 //只有当木棒长度能够被sum整除时,该木棒长度才算合理 33 if (sum % max == 0) { 34 parts = sum / max; 35 //搜索按木棍长度,从大往小进行, 这样可以避免不变要的搜索 36 if (search(0, len - 1, 0)) { 37 System.out.println(max); 38 break; 39 } 40 } 41 } 42 } 43 } 44 45 /** 46 * 尝试搜索使木棍能够凑成一个木棒 47 * @param res 当前这在合成的木棒的已合成的长度 48 * @param next 下一个需要搜索的木棍下标 49 * @param cpl 已经合成的木棒数 50 * @return 51 */ 52 private static boolean search(int res, int next, int cpl) { 53 // res = max 说明当前已经合成一个木棒 54 // cpl++ res置0 55 // next置为len-2, 因为此时len-1这个木棍肯定已经被用掉了,下次搜索肯定从len-2开始,其实这个并不重要,因为每次开始搜索的时候都会检查当前搜索的木棍used[next] 56 if (res == max) { 57 cpl++; 58 res = 0; 59 next = len - 2; 60 } 61 // 表明当前所有木棒已经合成完毕,返回 62 if (cpl == parts) { 63 return true; 64 } 65 66 // 当前还有木棍没有合并完,需进一步合并 67 while (next >= 0) { 68 // 如果当前木棍没有被使用过 69 if (used[next] == false) { 70 // 已合并+ s[next】 <= max 说明当前木棍可以加入到当前正在合并的木棒中 71 if (res + s[next] <= max) { 72 used[next] = true; 73 // 搜索成功返回 74 if (search(res + s[next], next - 1, cpl)) { 75 return true; 76 } 77 // 搜索不成功,回溯 78 used[next] = false; 79 // 当前正在合并的木棒长度res = 0, 且剩余木棍中并不能再合成木棒,搜索失败 80 if (res == 0) { 81 break; 82 } 83 // 可以合成一个当前的,但是剩余的不能合成一个木棒,搜索失败 84 if (res + s[next] == max) { 85 break; 86 } 87 // 其他情况仍然可以搜索 88 } 89 90 int i = next - 1; 91 while (i >= 0 && s[i] == s[next]) { 92 i--; 93 } 94 next = i; 95 int l_s = 0; 96 while (i >= 0) { 97 if (!used[i]) { 98 l_s += s[i]; 99 } 100 i--; 101 } 102 103 if (l_s < max - res) { 104 break; 105 } 106 continue; 107 } 108 next--; 109 110 } 111 return false; 112 } 113 114 }