POJ - 1011
题面:
Description
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
翻译
乔治拿起一根同样长度的木棍,随意地将其剪断,直到所有的部分长到不超过50个单位。
现在他想把木棒恢复到原来的状态,但是他忘记了他原来有多少根木棒,有多长。
请帮助他设计一个程序,计算出这些棍子的最小原始长度。
以单位表示的所有长度都是大于零的整数。
输入
输入包含两行代码块。
第一行是切割后的木棒零件数量,最多64根。
第二行包含由空格分隔的部分的长度。
文件的最后一行包含0。
输出
输出应该包含尽可能小的原始棒的长度,每一行一个。
思路
首先先判断每一根棍子可能有多长,将数据,从大到小代入进去DFS,重复长度的,被拒一根全部跳过,要注意超时。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
bool fuck(int a,int b)
{
return a>b;
}
int m[101],mm[101],n,k,c,x,gg;
int check(int y,int z)
{
if(y==0&&z==0)
return 1;
if(y==0&&z!=0)
return 0;
if(z==0)
z=x;
if(z==x)
gg=1;
else
gg++;
for(int i=gg;i<=n;i++)
{
if(mm[i]==1)
continue;
if(mm[i-1]==0&&m[i-1]==m[i])
continue;
if(z-m[i]>=0)
{
mm[i]=1;
gg=i;
if(check(y-1,z-m[i])==1)
return 1;
else
{
mm[i]=0;
if(z==x||m[i]==z)
return 0;
continue;
}
}
}
return 0;
}
int main()
{
int a,b;
bool ok=0;
while(1)
{
memset(m,0,sizeof(m));
cin>>n;
if(n==0)
{
break;
}
c=0;
for(int i=1;i<=n;i++)
{
cin>>m[i];
c+=m[i];
}
sort(m+1,m+n+1,fuck);
ok=0;
for(int i=m[1];i<=c/2;i++)
{
if(c%i==0)
{
k=0;
memset(mm,0,sizeof(mm));
x=i;
if(check(n,x)==1)
{
ok=1;
cout<<i<<endl;
break;
}
}
}
if(ok==0)
cout<<c<<endl;
}
return 0;
}