zoukankan      html  css  js  c++  java
  • POJ 1011 Sticks

    题目传送门

    //原址有中文翻译

    解题思路:

    求出总长度sum和小棒最长的长度max,则原棒可能的长度必在max~sum之间,然后从小到大枚举max~sum之间能被sum整除的长度len,用dfs求出所有的小棒能否拼凑成这个长度,如果可以,第一个len就是答案。

     

    下面就是关键的了,就是这道题dfs的实现和剪枝的设计:

          1.以一个小棒为开头,用dfs看看能否把这个小棒拼凑成len长,如果可以,用vis[i]记录下用过的小棒,然后继续以另外一个小棒为开头,以此类推。

          2.小棒的长度从大到小排序,这个就不解释了。

          3.如果当前最长的小棒不能拼成len长,那么就返回前一步,更改前一步的最长小棒的组合情况(这里不能是全部退出),不用再继续搜索下去了。

          4.最重要的,就是比如说17,9,9,9,9,8,8,5,2……如果当前最长小棒为17,它与第一个9组合之后dfs发现不能拼成len,那么17就不用和后面所有的9组合了,而直接和8开始组合。这个剪枝直接从TLE到16MS,很强大。

    //转自http://blog.sina.com.cn/s/blog_6635898a0100lgq0.html

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 int n,a[70],ans;
     9 bool flag,vis[70]; 
    10 
    11 bool cmp(int k,int b) {
    12     return k > b;
    13 }
    14 
    15 inline void dfs(int deep,int now,int i) {
    16     if(flag) return ;
    17     if(now == 0) {
    18         int k = 0;
    19         while(vis[k]) k++;
    20         vis[k] = true;
    21         dfs(deep + 1,a[k],k + 1);
    22         vis[k] = false;
    23         return ;
    24     }
    25     if(now == ans) {
    26         if(deep == n + 1) flag = true;
    27         else dfs(deep,0,1);
    28         return ;
    29     }
    30     for(int j = i;j <= n; j++) {
    31         if(!vis[j] && now + a[j] <= ans) {
    32             if(!vis[j-1] && a[j] == a[j-1]) continue;
    33             vis[j] = true;
    34             dfs(deep + 1,now + a[j],j + 1);
    35             vis[j] = false;
    36         }
    37     }
    38 }
    39 
    40 int main()
    41 {
    42     while(true) {
    43         scanf("%d",&n);
    44         if(n == 0) return 0;
    45         flag = false;
    46         int sum = 0;
    47         for(int i = 1;i <= n; i++) {
    48             scanf("%d",&a[i]);
    49             sum += a[i];
    50         }
    51         sort(a + 1,a + n + 1,cmp);
    52         for(ans = a[1];ans < sum; ans++) 
    53             if(sum % ans == 0) {
    54                 memset(vis,0,sizeof(vis));
    55                 dfs(0,0,1);
    56                 if(flag) break;
    57             }
    58         printf("%d
    ",ans);
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    C#的默认访问权限
    隐藏基类成员
    索引指示器的重载
    索引指示器
    vector
    string 函数
    细胞个数
    计蒜客 T1096 石头剪刀布
    计蒜客 T1125 判断字符串是否为回文
    计蒜客 T1152 成绩排序
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/11487527.html
Copyright © 2011-2022 走看看