POJ1011

题目:http://acm.pku.edu.cn/JudgeOnline/problem?id=1011

思路:深度搜索+剪枝,主要还是看你剪枝条件想的多不多。。。

 

  1. import java.io.BufferedReader;
  2. import java.io.InputStreamReader;
  3. import java.util.Arrays;
  4. import java.util.StringTokenizer;
  5. public class Main {
  6.     // 标记是否使用过这个棒子,在递归时后需要标记
  7.     static boolean[] used;
  8.     // 棒子总数量
  9.     static int len;
  10.     // 棒子的数组
  11.     static int[] s;
  12.     // 总长度
  13.     static int sum;
  14.     // 假设的原棒长
  15.     static int max;
  16.     // 棒子数量 = 总长度/原棒长
  17.     static int parts;
  18.     public static void main(String[] args) throws Exception {
  19.         BufferedReader read = new BufferedReader(new InputStreamReader(
  20.                 System.in));
  21.         while ((len = Integer.parseInt(read.readLine())) != 0) {
  22.             s = new int[len];
  23.             StringTokenizer take = new StringTokenizer(read.readLine());
  24.             int index = 0;
  25.             sum = 0;
  26.             used = new boolean[len];
  27.             while (take.hasMoreTokens()) {
  28.                 s[index] = Integer.parseInt(take.nextToken());
  29.                 sum += s[index++];
  30.             }
  31.             Arrays.sort(s);
  32.             // 起始假设原棒长=最长棒的长度
  33.             max = s[len - 1];
  34.             for (; max <= sum; max++) {
  35.                 // 穷举棒子长度,只取总长度模原长度=0的情况
  36.                 if (sum % max == 0) {
  37.                     // 原棒的数量
  38.                     parts = sum / max;
  39.                     // 递归搜索
  40.                     if (search(0, len - 10)) {
  41.                         System.out.println(max);
  42.                         break;
  43.                     }
  44.                 }
  45.             }
  46.         }
  47.     }
  48.     public static boolean search(int res, int next, int cpl) {
  49.         // 如果凑成了一根棒子,继续凑下面一个
  50.         if (res == max) {
  51.             // 这个是现在这个棒子的长度,初始化为0
  52.             res = 0;
  53.             // 这里等于len-2只是一个初始化,反正len-1肯定被占用了,我何不从len-2开始呢,反正后面还要判断有没有被使用过
  54.             next = len - 2;
  55.             // 这个是已经凑成的棒子数
  56.             cpl++;
  57.         }
  58.         // 如果凑成了parts这么多棒子,那就结束了,搜索完成
  59.         if (cpl == parts) {
  60.             return true;
  61.         }
  62.         // 从后往前搜索
  63.         while (next >= 0) {
  64.             // 如果没有被使用的话
  65.             if (used[next] == false) {
  66.                 // 那么判断下这根棒子能不能放进我现在剩余的空间里面
  67.                 if (res + s[next] <= max) {
  68.                     // 能放得进的话,那么标记这跟棒子已经使用过了
  69.                     used[next] = true;
  70.                     // 继续寻找下一根
  71.                     if (search(res + s[next], next - 1, cpl)) {
  72.                         // 返回结果为true表示全部凑成功了
  73.                         return true;
  74.                     }
  75.                     // 如果没有凑成功,我把这根棒子不放进去并标记为false
  76.                     used[next] = false;
  77.                     // 如果第一块的都没放不进去的话,那么说明找的有问题,直接退出了
  78.                     if (res == 0) {
  79.                         break;
  80.                     }
  81.                     // 如果现在本来应该尝试成功的(已经拼成了一个原棒,应该进入递归变成0的)却失败了,说明找的有问题
  82.                     if (res + s[next] == max) {
  83.                         break;
  84.                     }
  85.                 }
  86.                 // 找下一块不相等的棒子
  87.                 int i = next - 1;
  88.                 while (i >= 0 && s[i] == s[next]) {
  89.                     i--;
  90.                 }
  91.                 next = i;
  92.                 // 如果剩下的和比我需要的棒子还小的话,就不用凑了
  93.                 int l_s = 0;
  94.                 for (int j = next; j >= 0; j--) {
  95.                     if (!used[j]) {
  96.                         l_s += s[j];
  97.                     }
  98.                 }
  99.                 if (l_s < max - res) {
  100.                     break;
  101.                 }
  102.                 // 继续找下面的棒子
  103.                 continue;
  104.             }
  105.             // 说明这个棒子被用过了,找下面一个棒子
  106.             next--;
  107.         }
  108.         // 如果从这里出来的话,表示程序不能凑完所有棒子
  109.         return false;
  110.     }
  111. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值