zoukankan      html  css  js  c++  java
  • 牛客

    链接:https://ac.nowcoder.com/acm/problem/50243
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 32768K,其他语言65536K
    64bit IO Format: %lld

    题目描述

    乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。

    输入描述:

    第一行为一个单独的整数N表示砍过以后的小木棍的总数。第二行为N个用空格隔开的正整数,表示N根小木棍的长度。

    输出描述:

    输出仅一行,表示要求的原始木棍的最小可能长度。
    示例1
    输入
    9
    5 2 1 5 2 1 5 2 1
    输出
    6
    备注:
    1<=N<=60

    题目大意:
    给出n个小木棍,你的任务是把他们拼接起来,还原原来的木棍,求拼接后每个小木棍的最小长度。

    解题思路:
    这个题注意一定要用搜索做而不是二分,之前做过一个拆分木棍的题是二分,因为那个题长度和拆分的数量有一个线性关系,而这个合并木棍并没有,我们用DFS+剪枝AC这个题,因为要求最小的长度,我们先将木棍排序,因为要求拼成的最小的长度,我们要从这些木棍最长的开始往上枚举,对每一个枚举的长度进行搜索,搜索的状态是(剩余木棍的个数,枚举的长度,当前拼成木棍剩余长度,和当前枚举的哪一根木棍)另外需要剪枝操作,剪枝有以下几点:

    1. 如果当前木棍是当去拼枚举长度的第一根,则需要剪掉,因为我们从最长的开始枚举,如果连第一个都拼不上,那么后面的肯定也拼不上。
    2. 如果当前木棍是当去拼枚举长度的最后一根,也需要剪掉,因为木棍是从大到小排,如果这个长度都不行,那后面的长度肯定比这个还小,肯定也拼不上,剪掉。
    3. 如果当前小木棍拼不上,那么和当前木棍长度相同的木棍肯定也拼不上,直接过滤掉和当前木棍长度相等的木棍即可。

    AC代码:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 65;
    int a[N],n;
    bool vis[N];
    bool cmp(int a,int b) { return a>b; }
    bool dfs(int num,int len,int rest,int now)
    {
        if(num==0&&rest==0)//当前剩余0个木棍且当前要拼的长度为0时代表可以拼成
          return true;
        if(rest==0)
          rest=len,now=0;
        for(int i=now;i<n;i++)
        {
            if(a[i]>rest)
              continue;
            if(!vis[i])
            {
                vis[i]=true;
                if(dfs(num-1,len,rest-a[i],i+1))
                  return true;
                vis[i]=false;
                if(a[i]==rest||len==rest)//第一个木棍和最后一个木棍的时候剪掉
                  break;
                while(a[i]==a[i+1])//过滤掉相同的木棍
                  i++;
            }
        }
        return false;
    }
    int main()
    {
        int sum=0,s=0;
        scanf("%d",&n);
        memset(vis,false,sizeof vis);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]<=50)
              sum+=a[i];
            else
              s++;  
        }
        n-=s;
        sort(a,a+n,cmp);
        for(int i=a[0];i<=sum;i++)//从最大的开始枚举
        {
            if(sum%i==0)
              if(dfs(n,i,0,0))
              {
                  printf("%d
    ",i);
                  break;
              }
        }
        return 0;
    }
    
  • 相关阅读:
    Visual Studio 2010使用Visual Assist X的方法
    SQL Server 2000 评估版 升级到 SQL Server 2000 零售版
    双网卡多网络单主机同时访问
    开发即过程!立此纪念一个IT新名词的诞生
    delphi dxBarManager1 目录遍历 转为RzCheckTree2树
    5320 软件集合
    delphi tree 从一个表复制到另一个表
    DELPHI 排课系统课表
    长沙金思维 出现在GOOGLE的 金思维 相关搜索里啦!!
    如何在DBGrid的每一行前加一个单选框?
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294259.html
Copyright © 2011-2022 走看看