题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入描述:
第一行为一个单独的整数N表示砍过以后的小木棍的总数。第二行为N个用空格隔开的正整数,表示N根小木棍的长度。
输出描述:
输出仅一行,表示要求的原始木棍的最小可能长度。
示例1
输入
9 5 2 1 5 2 1 5 2 1
输出
6
备注:
1≤N≤60
思路:
1,相同长度->原始长度为总长度的因子
2,切割->原始长度>=max的长度
3,使用dfs
代码:
#include<bits/stdc++.h>
using namespace std;
int a[100],vis[120],sum=0,mx=-1,n;
bool dfs(int cur,int cnt,int x,int len){//无void,不为回溯
if(cnt*len==sum)return 1; //结果
if(cur==len)return dfs(0,cnt+1,1,len); //递归判断,从一开始防止未被用到的漏掉
for(int i=x;i<=n;++i){ //循环暴力
if(vis[i]||a[i]+cur>len)continue;
vis[i] = 1 ;
if ( dfs(cur+a[i],cnt,i+1,len) ) return 1;//递归
vis[i] = 0 ;
if (cur == 0) return 0 ;
while ( a[i] == a[i+1] ) ++i ;//相同长度没有重复使用的意义.
}
return 0 ;
}
// bool cmp( int a,int b ){
// return a>b;
// }
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",a+i);
sum+=a[i];mx=(a[i]>mx)?a[i]:mx;//记录和和最大值
}
sort( a+1,a+1+n,[](const int &a,const int &b){
return a>b;
} );//从大到小遍历
// for(int i=1;i<=n;++i){
// cout<<a[i]<<'\n';
// }
// // sort(a+1,a+1+n,cmp);
for(int i=mx;i<=sum;++i){
if(sum%i==0&&dfs(0,0,1,i)){
cout<<i; return 0;//最小符合条件的和
}
}
return 0;
}