题目:https://ac.nowcoder.com/acm/problem/50243
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入描述:
第一行为一个单独的整数N表示砍过以后的小木棍的总数。第二行为N个用空格隔开的正整数,表示N根小木棍的长度。
输出描述:
输出仅一行,表示要求的原始木棍的最小可能长度。
样例1
输入
9
5 2 1 5 2 1 5 2 1
输出
6
备注:
1<=N<=60
题解:这是一道搜索题,这道题的思路是在拼接木棍时,如果上一个木棍拼完,那么就从下一根最长的木棍拼起,如果没拼完,就从最大的开始拼,如果最大的接上过长就往小试探,当已经减掉了这根木棍的长度时,就不需要往下继续找了。
#include <bits/stdc++.h> typedef long long ll; using namespace std; int n,tong[105],sum,a[105],MAX,ok=1,len,MIN; int dfs(int cur,int x,int y) { if(cur==0) ok=1; if(ok==1) return 0; if(y==0) { dfs(cur-1,MAX,len); return 0; } int i; for(i=x; i>=MIN&&ok==0; --i) { if(tong[i]!=0&&i<=y) { tong[i]--; dfs(cur,i,y-i); tong[i]++; if(y==len||y-i==0) break;//优化1 } } return 0; } int main() { ios::sync_with_stdio(0),cin.tie(0); int i,j; while(cin>>n&&n!=0) { memset(tong,0,sizeof(tong)); sum=0,MAX=0,MIN=99; for(i=1; i<=n; i++) { cin>>a[i]; if(a[i]>50) continue; sum+=a[i]; tong[a[i]]++; MAX=max(MAX,a[i]); MIN=min(MIN,a[i]); } for(i=MAX; i<=sum/2; i++)//优化2 { if(sum%i!=0) continue; len=i; ok=0; dfs(sum/i,MAX,i); if(ok) { cout<<i<<endl; break; } } if(i>sum/2) cout<<sum<<endl; } return 0; }