zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

    题目描述
    乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。

    现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。

    给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。

    输入输出格式
    输入格式:
    输入文件共有二行。

    第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65

    (管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!)

    第二行为N个用空个隔开的正整数,表示N根小木棍的长度。

    输出格式:
    输出文件仅一行,表示要求的原始木棍的最小可能长度

    输入输出样例
    输入样例#1:
    9
    5 2 1 5 2 1 5 2 1
    输出样例#1:
    6
    说明
    2017/08/05

    数据时限修改:

    -#17 #20 #22 #27 四组数据时限500ms

    -#21 #24 #28 #29 #30五组数据时限1000ms

    其他时限改为200ms(请放心食用)


      分析:CL大佬讲课的时候讲到了这题,于是就来做一下。但是讲的时候没听,于是做的时候遇到了瓶颈,还是参考了five20大佬的博客。确定了搜索的思路,那么要考虑的就是如何剪枝,这题真的是一道练习搜索剪枝的绝(e)世(xin)好(gui)题。总共需要用到一下几种剪枝:

      1,搜索范围:很显然,答案肯定是在[maxn,sum]内,maxn为给定木棍的最大长度,sum为给定木棍长度之和,同时正确答案一定能被sum整除,所以搜的时候范围就确定在maxn到sum/2之间能把sum整除的所有整数。如果在该范围内均不满足,那么答案就是sum。

      2,搜索顺序:由上面得出的范围可知,从大到小搜索更优,而且根据题目可知,木棍长度<=50,那么也不需要快排了,直接桶排,记录每种长度的木棍的数目即可。

      3,如果搜索过程中已经使用过长度为x的木棍,那么下一层搜索直接从x开始从大到小搜,因为显然此刻使用了x那么比x长的都已经不可行了。

      4,如果某次搜索时如果当前长度为0或当前长度加选择木棍的长度等于目标长度,那么搜完以后直接break,因为是从大到小枚举,因此再小的木棍就不能达到目标长度了。(这个优化可能这么说并不太好理解,结合代码应该就好懂了)

      Code:

      

    //It is made by HolseLee on 19th Apr 2018
    //Luogu.org P1120
    #include<bits/stdc++.h>
    using namespace std;
    const int N=101;
    int n,num[N],sum,cnt;
    int maxn=0,minn=N;
    inline void dfs(int tar,int now,int len,int m)
    {
      if(!tar){printf("%d",len);exit(0);}
      if(now==len){
        dfs(tar-1,0,len,maxn);
        return;}
      for(int i=m;i>=minn;i--){
        if(now+i<=len&&num[i]){
          num[i]--;
          dfs(tar,now+i,len,i);
          num[i]++;
          if(!now||now+i==len)
        break;}
      }
    }
    int main()
    {
      ios::sync_with_stdio(false);
      cin>>n;int x;
      for(int i=1;i<=n;i++){
        cin>>x;
        if(x<=50){
          num[x]++;cnt++;
          maxn=max(maxn,x);
          minn=min(minn,x);
          sum+=x;}
      }
      for(int i=maxn;i<=sum/2;i++){
        if(sum%i==0)dfs(sum/i,0,i,maxn);
      }
      printf("%d",sum);
      return 0;
    }
  • 相关阅读:
    【推荐】com.alibaba方式xml转json,能将xml的所有属性方法,全部转化为json
    关于使用JAXB读取xml文档转换为java对象报错:类的两个属性具有相同名称com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsExc...
    java正则,将<a或者</a,尖括号后面的字母改成大写
    javaben转xml
    三次握手四次挥手
    RPC接口测试(六)RPC协议解析(重要!重要!重要!)
    os.popen(cmd) 与 os.system(cmd) 的区别
    jmeter测试webSocket接口
    Ubuntu20.04 体验和美化
    API可视化管理平台YApi
  • 原文地址:https://www.cnblogs.com/cytus/p/8886465.html
Copyright © 2011-2022 走看看