日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

牛客

發(fā)布時間:2023/12/13 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 牛客 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

鏈接:https://ac.nowcoder.com/acm/problem/50243
來源:牛客網(wǎng)

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld

題目描述

喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過50。現(xiàn)在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,編程幫他找出原始木棍的最小可能長度。

輸入描述:

第一行為一個單獨的整數(shù)N表示砍過以后的小木棍的總數(shù)。第二行為N個用空格隔開的正整數(shù),表示N根小木棍的長度。

輸出描述:

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

題目大意:
給出n個小木棍,你的任務(wù)是把他們拼接起來,還原原來的木棍,求拼接后每個小木棍的最小長度。

解題思路:
這個題注意一定要用搜索做而不是二分,之前做過一個拆分木棍的題是二分,因為那個題長度和拆分的數(shù)量有一個線性關(guān)系,而這個合并木棍并沒有,我們用DFS+剪枝AC這個題,因為要求最小的長度,我們先將木棍排序,因為要求拼成的最小的長度,我們要從這些木棍最長的開始往上枚舉,對每一個枚舉的長度進(jìn)行搜索,搜索的狀態(tài)是(剩余木棍的個數(shù),枚舉的長度,當(dāng)前拼成木棍剩余長度,和當(dāng)前枚舉的哪一根木棍)另外需要剪枝操作,剪枝有以下幾點:

如果當(dāng)前木棍是當(dāng)去拼枚舉長度的第一根,則需要剪掉,因為我們從最長的開始枚舉,如果連第一個都拼不上,那么后面的肯定也拼不上。如果當(dāng)前木棍是當(dāng)去拼枚舉長度的最后一根,也需要剪掉,因為木棍是從大到小排,如果這個長度都不行,那后面的長度肯定比這個還小,肯定也拼不上,剪掉。如果當(dāng)前小木棍拼不上,那么和當(dāng)前木棍長度相同的木棍肯定也拼不上,直接過濾掉和當(dāng)前木棍長度相等的木棍即可。

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)//當(dāng)前剩余0個木棍且當(dāng)前要拼的長度為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;
}

總結(jié)

以上是生活随笔為你收集整理的牛客的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。