POJ 1011-Sticks

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 }
posted @ 2012-10-28 14:24  feiling  阅读(354)  评论(0编辑  收藏  举报