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

      题意:有若干根一样长的棍子,然后将其随机地截断成n跟不同长短的小棍子;给你这n根棍子,让你求原来的棍子可能是多长,并且要求其长度最小。

      题解:很经典的深搜剪枝。需要几个剪枝就不会TLE了。根据给定假设长度用dfs去判断 这一步实现应该不是问题。(直接排序后从大往小的扫一遍过去判断是不行的;一开始就wa这,,,后面才想到深搜=_=...)直接列出所需要的几个剪枝的地方: (1)先将n根小棍子从大到小排序。 (2)以假设长度从最大的棍子长度Max到总和sum遍历;如果sum%temp==0,则对假设长度temp进行dfs。 (3)在对假设长度temp进行dfs的时候,是要判断到sum/temp根temp长度都能拼成才算true的;所以只要判断到一根temp长度的棍子是拼不成的,那么后面剩下的若干根就不必判断了直接跳出。

       详细见代码注释:

     1 /**
     2 * @author Wixson
     3 */
     4 #include <iostream>
     5 #include <cstdio>
     6 #include <cstring>
     7 #include <cmath>
     8 #include <algorithm>
     9 #include <queue>
    10 #include <stack>
    11 #include <vector>
    12 #include <utility>
    13 #include <map>
    14 #include <set>
    15 const int inf=0x3f3f3f3f;
    16 const double PI=acos(-1.0);
    17 const double EPS=1e-8;
    18 using namespace std;
    19 typedef long long ll;
    20 typedef pair<int,int> P;
    21 
    22 int n,sum,Max,cnt;
    23 int a[70];
    24 int book[70]; //标记数组
    25 bool cmp(int a,int b)
    26 {
    27     return a>b;
    28 }
    29 //pos为当前在a的位置,left代表还剩几根没判断,len代表当前判断的这根还有多少长度要拼
    30 int dfs(int pos,int left,int len)
    31 {
    32     if(len==0)
    33     {
    34         if(left==1)
    35         {
    36             return 1;
    37         }
    38         else
    39         {
    40             return dfs(0,left-1,Max);
    41         }
    42     }
    43     //
    44     for(int i=pos;i<n;i++)
    45     {
    46         if(a[i]>len) continue;
    47         if(book[i]) continue;
    48         book[i]=1;
    49         if(dfs(pos+1,left,len-a[i]))
    50         {
    51             return 1;
    52         }
    53         book[i]=0;
    54         //
    55         if(len==Max) return 0;//最重要的剪枝,如果假设长度有一根拼不成就直接跳出dfs
    56         //
    57         while(i+1<n&&a[i]==a[i+1]) i++;//当前a[i]拼不成,那么后面跟其相同长度的都跳过
    58     }
    59     //
    60     return 0;
    61 }
    62 int main()
    63 {
    64     //freopen("input.txt","r",stdin);
    65     while(scanf("%d",&n)&&n)
    66     {
    67         flag=0;
    68         Max=-inf;
    69         sum=0;
    70         for(int i=0; i<n; i++) scanf("%d",&a[i]),sum+=a[i],Max=max(Max,a[i]);
    71         //
    72         sort(a,a+n,cmp); //从大到小排序
    73         //
    74         while(true)
    75         {
    76             if(sum%Max==0) //取余不为0的话肯定就不用判断了
    77             {
    78                 cnt=sum/Max; //要判断cnt根
    79                 memset(book,0,sizeof(book));
    80                 if(dfs(0,cnt,Max)) break;
    81             }
    82             //
    83             Max++;
    84         }
    85         printf("%d
    ",Max);
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    基于OEA框架的客户化设计(三) “插件式”DLL
    小技巧、小工具列表
    OEA中的AutoUI重构(3) 评审会议后的设计
    基于OEA框架的客户化设计(一) 总体设计
    数据层扩展包EFCachingProvider 总结
    中国软件工程大会总结
    性能优化总结(二):聚合SQL
    招 .Net 开发人员 (北京) 已招满
    War3Share开源
    正则表达式:匹配字符串中除了"abc"以外的所有其它部分
  • 原文地址:https://www.cnblogs.com/geek1116/p/6397060.html
Copyright © 2011-2022 走看看