Description
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。
Input
输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。
Output
为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6
5
这题codves有个削弱版3498 一组数据而且很水。
解题思路;
下午刚开始想,没想到任何数据结构,二分不会,只能是搜索了。瞄了一眼数据范围这肯定得剪枝,而且还是大剪枝!难就难在剪枝验证答案上。如果不验证答案的话codves能水60分poj没敢试。
1.认真读题不难想出答案肯定比现在最长的木棍长,比总加和短。并且总加和%答案肯定==0。
2.然后再想如果从大的开始搜肯定比从小的开始更容易得到答案,正确性自己(ˇˍˇ) 想~。不难。
3.只要有一个木棍不能匹配就不用搜了。
还有剪枝但我没写 so 我只跑了69ms 。
----------------------------------------------------------代码如下
#include <iostream>#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int size=10010;
int num[size],n;
bool used[size];
int sum;
//交换函数使sort从大到小排序
int cmp(int x,int y)
{
return x>y;
}
//判断木棍是否能组成答案,验证。
bool pd(int tot,int unused,int dqc,int len) //tot 总数,unused没用过得 dqc 当前与验证的答案差多少 len 要验证的答案
{
if(unused==0&&dqc==0) //如果剩余木棍为0,剩余长度为0,拼接完成
return true;
if(dqc==0) //当前拼接木棍剩余长度为0;
dqc=len; //尝试新的一个原始长度
for(int i=1;i<=tot;i++) //从第一个开始找到最好一个
{
if(used[i]==true) //如果用了 跳走
continue;
if(num[i]>dqc) //如果当前的木棍比当前差的要少 跳走
continue;
used[i]=true;
if(pd(tot,unused-1,dqc-num[i],len)==true) //如果答案符合要求
return true;
used[i]=false; //寻找下一个木棍
if(num[i]==dqc||dqc==len) //如果某个木棍一上来就等于答案差或最好答案差还是等于原长说明没有木棍跟它匹配 结束循环
break;
}
return false;
}
//初始化 千万别忘了!!!
void init()
{
memset(num,0,sizeof(num));
memset(used,0,sizeof(used));
sum=0;
}
int main()
{
scanf("%d",&n);
while (n!=0)
{
init();
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
sum+=num[i];
}
sort(num+1,num+n+1,cmp);
for(int i=num[1];i<=sum;i++)
{
if(sum%i==0)
{
if(pd(n,n,0,i)==true)
{
printf("%d\n",i);
break;
}
}
}
scanf("%d",&n);
}
return 0;
}