• 洛谷 1120 小木棍(数据加强版)


    题目描述

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

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

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

    输入输出格式

    输入格式:

    输入文件共有二行。

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

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    9
    5 2 1 5 2 1 5 2 1
    
    输出样例#1: 
    6
    Solution
      
    首先我们想到把所有木棍长度加起来,然后答案肯定是总长度的因数。这时从小到大枚举,如果可以凑出则直接输出答案,结束程序,按以上方法不加任何剪枝27分。
    剪枝一:从大到小排序,从大的枚举层数越少。(33分)
    剪枝二:如果当前拼出的长度加上最小的任然超出期望长度,则剪枝。(36分)
    剪枝三:玄学剪枝,感谢520巨佬教的,然而并没有听懂(67分)
    剪枝四:因为有相同的数,所以如果x搜不出答案,则相同的x都不同搜了。(用桶排的小伙伴不需要这个)(100分)
      以下是代码,然而用桶牌的小伙伴看不懂可以去520的巨佬博客看看,贴下他的链接
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int cnt,a[70],maxn,sum[70];
    bool vis[70];
    void check(int step,int x,int num,int all,int last)
    {
        if(num==x&&step==all-1) {cout<<x<<endl; exit(0);}
        if(num==x) {num=0; step++; last=0;}
        if(x-num<a[cnt])    return ;//剪枝TOW
        for(int i=last+1;i<=cnt;i++)
        {
            if(vis[i]==0&&num+a[i]<=x) 
            {
                vis[i]=1;
                check(step,x,num+a[i],all,i);
                vis[i]=0;
                if(!num||num+a[i]>=x) break ;//玄学剪枝THREE
                while(a[i]==a[i+1]) i++;//剪枝FOUR
            }
        }
        return ;
    }    
    bool cmp(int x,int y)
    {
        return x>y;
    }
    int main()
    {
        int n,maxn=0,maxnn=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(x<=50){a[++cnt]=x; maxn+=a[cnt]; maxnn=max(a[cnt],maxnn);}
        }
        sort(a+1,a+1+cnt,cmp);//剪枝ONE
        for(int i=maxnn;i<=maxn;i++)//从最大的棍子长度开始枚举,应该也算一个剪枝吧。
        {
            if(maxn%i==0)    
                {
                    memset(vis,0,sizeof(vis));
                    check(0,i,0,maxn/i,0);
                }
        }
        return 0;
    }
    
    
    
    
    
  • 相关阅读:
    SQL横表纵表转换和对比
    计算机书籍
    附加原型链
    Object.create()
    解构赋值是浅拷贝
    Object.keys(xxx)与Object.getOwnPropertyNames(xxx)
    剑指 Offer 45. 把数组排成最小的数
    剑指 Offer 46. 把数字翻译成字符串
    剑指 Offer 43. 1~n 整数中 1 出现的次数
    剑指 Offer 41. 数据流中的中位数
  • 原文地址:https://www.cnblogs.com/Le-mon/p/8591051.html
Copyright © 2020-2023  润新知