zoukankan      html  css  js  c++  java
  • P1120 小木棍 [数据加强版]

    题目描述

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

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

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

    输入输出格式

    输入格式:

    共二行。

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

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

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

    输出格式:

    一个数,表示要求的原始木棍的最小可能长度

    输入输出样例

    输入样例#1: 复制

    9
    5 2 1 5 2 1 5 2 1

    输出样例#1: 复制

    6

    说明

    2017/08/05

    数据时限修改:

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

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

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


    从木棍中小于等于50的最大值开始向后循环,如果(k)是总和的因数就dfs判断是否合法。
    判断方法:用所有的小木棍能否拼出(sum/k)根木棍
    剪枝:

    1. 用桶存储木棍
    2. 每次从大向小枚举木棍加入
    3. 每次需要新拼一根木棍时先把当前最大的小木棍加入。如果剩余部分不能拼出直接返回(false)

    4. 如果有与剩余长度相同的一根小木棍则不用考虑使用其余小木棍拼出此长度
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    int i,m,n,j,k,c[51],sum,maxx;
    bool check(int l,int now,int k,int d[],int st) 
    {
        if(k==0) return check(l+1,now,now,d,maxx);	
        if(l==sum/now)  return 1;
        if(k==now) 
        {
            int t=maxx; while(!d[t]) t--; 
            d[t]-=1; 
            if(check(l,now,k-t,d,min(maxx,k-t))) return 1;
            d[t]+=1; return 0; 
        }
    
        for(int i=min(k,st);i>=1;i--)
        {
            if(d[i] &&(k>=i))
            {
                d[i]-=1;
                if(k==i){
                    if(check(l+1,now,now,d,maxx)) return 1;
                    d[i]+=1; return 0;
                }
                else if(check(l,now,k-i,d,i)) return 1;
                d[i]+=1;
            }
        }
        return 0;
    
    }
    
    int main() 
    { 
        scanf("%d",&n); 
        for(i=1;i<=n;i++) 
        {
            scanf("%d",&m); 
            if(m<=50) {
                sum+=m; 
                maxx=max(maxx,m); 
                c[m]+=1; 
                j+=1; 
            } 
        } 
        c[0]=0x3f3f3f3f;
        for(int now=maxx;now;now++)
        {
            while(sum%now) now++; 
            int d[51]; 
            for(int i=0;i<=50;i++) d[i]=c[i]; 
            if(check(0,now,now,d,maxx)) 
            {
                printf("%d",now);
                break;
            }
        }
    }
    
  • 相关阅读:
    Python 里的下划线
    浅谈TCP拆包粘包问题
    40 张图带你搞懂 TCP 和 UDP
    头条面试官问:如何保证网络传输的可靠性?这就很尴尬了
    TCP协议灵魂12问,面试总会用得到(建议收藏)
    TCP网络握手
    HTTP1.0、HTTP1.1和HTTP2.0的区别
    面试官:这波HTTP究极combo,你顶得住吗?_chuhe1989的博客-CSDN博客
    腾讯面试官:说一下Android网络知识和框架?
    网络通信必备基础之Http协议&TCP/IP协议(二)
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/9510011.html
Copyright © 2011-2022 走看看