【题目大意】:一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。计算这组原始木棒的可能最小长度。
【解题思路】:明显的dfs。注意下面几点。
1.组合木棒时优先选择长的木棍。
2.木棒的长度一定是所有木棍长度的和的约数。
4.长度相同的两根木棒,前面的一根没被组合,后面的一根也无法被组合。
5.如果此次是在尝试第i个木棒的第一段,最大的切割下来的木棒组合不成功,则直接退回去。
【代码】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
int n,sum,ans;
int len[100];
int vis[100];
bool cmp(const int &a,const int &b){
return a>b;
}
bool solve_dfs(int anss,int now,int j,int cnt){
if (anss*cnt==sum) return true;
for (int i=j; i<n; i++){
if (vis[i]==1) continue;
if (len[i]==len[i-1] && !vis[i-1]) continue;
if (now+len[i]==anss){
vis[i]=1;
if (solve_dfs(anss,0,0,cnt+1)) return true;
vis[i]=0;
return false;
}
else{
if (now+len[i]<anss){
vis[i]=1;
if (solve_dfs(anss,now+len[i],i+1,cnt)) return true;
vis[i]=0;
if (now==0) return false;
}
}
}
return false;
}
int main() {
while (~scanf("%d",&n)){
if (n==0) break;
sum=0;
for (int i=0; i<n; i++){
scanf("%d",&len[i]);
sum+=len[i];
}
ans=-1;
sort(len,len+n,cmp);
for (int i=len[0]; i<sum; i++){
if (sum%i!=0) continue;
memset(vis,0,sizeof(vis));
if (solve_dfs(i,0,0,0)) {
ans=i;
break;
}
}
if (ans==-1) ans=sum;
printf("%d\n",ans);
}
return 0;
}