题目: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;
}



京公网安备 11010502036488号