AC日记——小木棍【数据加强版】 洛谷 P1120

题目描述

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

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

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

输入输出格式

输入格式:

输入文件共有二行。

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

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

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

输出格式:

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

输入输出样例

输入样例#1:
9
5 2 1 5 2 1 5 2 1
输出样例#1:
6



思路:
  大搜索;
  (思路来源:http://blog.csdn.net/chai_jing/article/details/52450419)


来,上代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n,len[101],cnt,maxlen,ans,Len,tot;

bool if_[101],if_re;

bool dfs(int now,int le,int num)
{
    if(num==tot+1) return false;
    if(le==0)
    {
        if(num==tot) return true;
        return dfs(1,Len,num+1);
    }
    for(int i=now+1;i<=n;i++)
    {
        if(le-len[i]>=0)
        {
            if(!if_[i])
            {
                if_[i]=true;
                if(dfs(i,le-len[i],num)) return true;
                if_[i]=false;
                if(len[i]==le) break;
                if(le==Len) break;
                while(len[i+1]==len[i]) i++;
            }
        }
    }
    return false;
}

bool check(int lenth)
{
    Len=lenth;
    tot=cnt/lenth;
    for(int i=2;i<=n;i++) if_[i]=false;
    return dfs(1,Len-len[1],1);
}

bool cmp(int a,int b)
{
    return a>b;
}

int main()
{
    int n_,pos;
    scanf("%d",&n_);
    for(int i=1;i<=n_;i++)
    {
        scanf("%d",&pos);
        if(pos<=50)
        {
            maxlen=max(pos,maxlen);
            len[++n]=pos,cnt+=pos;
        }
    }
    sort(len+1,len+n+1,cmp);
    for(int i=maxlen;i<=cnt;i++)
    {
        if(cnt%i==0&&check(i))
        {
            ans=i;
            break;
        }
    }
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6644057.html