Sticks
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 contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
Output
The output should 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
题意:给出一定数量的小木棒的长度,它是由等长的若干木棒随意砍断所得到的。对于给定的一组小木棒,请求出原始木棒的最小长度。
思路:设所有木棍的总长度为 Sum, 最终的答案(长度)是 L。 1. 首先要明白, Sum一定要能被 L 整除。
2. L 一定 大于等于 题目给出的最长的木棍的长度 Max。 由上述两点,我们想到,可以从 Max 开始递增地枚举 L, 直到成功地拼出 Sum/L 支长度为 L 的木棍。
代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int len[110],used[110],sum,l,n;
int dfs(int m,int left)
{
if(m==0&&left==0)//m为剩余未用的木棒数,left为当前正在拼接的木棒和假定的木棒长度l比还缺少的长度
return 1;
if(left==0)//一根刚刚拼完开始拼新的一根
left=l;
for(int i=n-1;i>=0;i--)
{
if(!used[i]&&len[i]<=left)
{
if(i>0)
{
if(!used[i-1]&&len[i-1]==len[i])//第一次剪枝
continue;//如果上次的木棒没有用,那这次与它相同长度的未使用的木棒也不可用,直接跳过
//break;
}
used[i]=1;
if(dfs(m-1,left-len[i]))
return 1;
else
{
used[i]=0;
if(len[i]==left||left==l)//len[i]==left减去搜索过程中不符荷的数,left==l当木棒的首不符合的,后面的就都不符合了,不用继续搜索
return 0;
}
}
}
return 0;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
sum=0;
int i,j;
for(i=0;i<n;i++)
{
scanf("%d",&len[i]);
sum+=len[i];
}
sort(len,len+n);
for(l=len[n-1];l<=sum/2;l++)
{
if(sum%l)//所求的木棒的长度必须是总长度的倍数
continue;
memset(used,0,sizeof(used));
if(dfs(n,l))
{
printf("%d\n",l);
break;
}
}
if(l>sum/2)//如果假设的长度大于总产度的一半,就为总长度
printf("%d\n",sum);
}
return 0;
}