题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入输出格式
输入格式:
输入文件共有二行。
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65
(管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!)
第二行为N个用空个隔开的正整数,表示N根小木棍的长度。
输出格式:
输出文件仅一行,表示要求的原始木棍的最小可能长度
输入输出样例
说明
2017/08/05
数据时限修改:
-#17 #20 #22 #27 四组数据时限500ms
-#21 #24 #28 #29 #30五组数据时限1000ms
其他时限改为200ms(请放心食用)
题目链接:https://www.luogu.org/problemnew/show/P1120
解题报告:
一道很棒的搜索题,要加一堆剪枝才能过,提高一下暴力的姿势水平.
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
int a[66],used[66];
int n,cnt,x,sum,maxx;
#define FOR(s,t) for(register int i=s;i<=t;++i)
inline void dfs(int tot,int t,int sec,int now){
if(t*sec==sum)printf("%d\n",sec),exit(0);
if(sum-tot<a[cnt])return;
if(tot==sec){
dfs(0,t+1,sec,1);
return;
}
FOR(now,cnt){
if(!used[i]&&a[i]+tot<=sec){
used[i]=1;
dfs(tot+a[i],t,sec,i+1);
used[i]=0;
if(a[i]+tot==sec||tot==0)break;
while(a[i]==a[i+1])++i;
}
}
return;
}
inline bool cmp(int a,int b){
return a>b;
}
int main(){
scanf("%d",&n);
FOR(1,n){
scanf("%d",&x);
if(x<=50)a[++cnt]=x,sum+=x,maxx=max(maxx,x);
}
sort(a+1,a+cnt+1,cmp);
FOR(maxx,sum/2)if(sum%i==0)dfs(0,0,i,1);
printf("%d\n",sum);
return 0;
}