George took sticks of the same length and cut them randomly until all parts became at most 50 units
long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally
and how long they were originally. Please help him and design a program which computes the smallest
possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input file contains blocks of 2 lines. The first line contains the number of sticks parts after cutting.
The second line contains the lengths of those parts separated by the space. The last line of the file
contains ‘0’.
Output
The output file contains the smallest possible length of original sticks, one per line.
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6
5
题意: 第一行给出一个数n,第二行有n个数,这n个数最初是有未知根木棒切割而成,现在把这些木棒拼接在一起,拼成长度相同的木棒,输出最短长度。
思路: 拼成的木棒长度一定在序列中的最大值和所有木棒长度之和,那么对这个区间中的每个数进行便利,求出能拼接的最短长度。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[100],n,m,ans;
int maxx,minn;
bool flag;
void dfs(int x,int s,int len,int st)//需要找的个数 拼接之和 需要找多少根 最大值
{
if(!x)//找完了
{
ans=len;
flag=true;
}
if(flag)
return;
if(s==len)//找到一根木棒
{
dfs(x-1,0,len,maxx);
return;
}
for(int i=st;i>=minn;i--)
{
if(a[i]&&s+i<=len)
{
a[i]--;
dfs(x,s+i,len,i);
a[i]++;
if(!s)
break;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)
break;
int sum=0;
memset(a,0,sizeof(a));
maxx=0,minn=1000,flag=0;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
if(x>50)
continue;
a[x]++;//出现过几次
sum+=x;
if(x>maxx)
maxx=x;
if(x<minn)
minn=x;
}
for(int i=maxx;i<=sum;i++)//对序列中的最大值和所有值之和中的每个数进行便利,找到所需木棒的最短长度
{
if(sum%i==0)
dfs(sum/i,0,i,maxx);//需要找长度为i的木棒sum/i根 当前为止拼接的木棒长度 需要拼接长度为i的木棒 拼接区间
if(flag)
break;
}
printf("%d\n",ans);
}
return 0 ;
}