题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入输出格式
输入格式:
共二行。
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65N≤65
(管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!)
第二行为N个用空个隔开的正整数,表示N根小木棍的长度。
输出格式:
一个数,表示要求的原始木棍的最小可能长度
输入输出样例
输入样例#1:
9
5 2 1 5 2 1 5 2 1
输出样例#1:
6
解释:暴力很好写,主要是剪枝,这里有4点,1.从最大木板开始搜,2.按从大向小搜避免重复,3.如果凑成整块后,以后的小的凑不出来,那么必然凑不出来,4.如果刚开始后大的凑不出来,小的必然也凑不出来。
#include<cstdio>
#include<cstdlib>
const int N = 70 ;
int n , cnt , tot , maxn , minn , tm[ N ];
void dfs( int res , int sum , int target , int p ) {
if(res==0){
printf("%d", target );
exit(0);
}
if(sum==target){
dfs(res - 1,0,target, maxn );
return;
}
for( int i = p ; i >= minn ; i -- ){
if( tm[ i ] && i + sum <= target ){
tm[ i ] -- ;
dfs( res , sum + i , target , i );
tm[ i ] ++ ;
if ( sum == 0 || sum + i == target )
break;
}
}
return;
}
int main() {
scanf("%d" , &n ) ;
minn = N ;
int temp;
while( n -- ) {
scanf("%d" , &temp );
if( temp <= 50 ) {
cnt ++;
tm[ temp ] ++;
tot += temp;
maxn = maxn > temp ? maxn : temp ;
minn = minn < temp ? minn : temp ;
}
}
for( int i = maxn ; i <= tot ; i ++ ) {
if( tot % i == 0 ) {
dfs( tot / i , 0 , i , maxn );
}
}
printf("%d" , tot );
return 0;
}