题目描述:(此题目是2012北大信科夏令营上机考试题目)
-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
- 乔治拿来一组等长的木棒,将它们随机地裁断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。 输入
- 输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。 输出
- 为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。 样例输入
-
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
样例输出
-
6 5
从下面几个方面考虑:
1. 原始木棍的长度应该大于等于折断子木棍的最大长度
2.所有子木棍的长度之和应该应该能够被当前猜测的子木棍的长度整除
3.满足2后,还应该在2假设的原木棍的长度的要求下组合成n个木棍
4.组合木棍可以采用递归的思想进行,函数原型采用bool makeup(int n,int l,int sl),代表用n个子木棍组合成原始长度为l的m(m值任意,与此题目无关)个子木棍和一个长度为sl的木棍,递归出口为剩余n=0个子木棍时sl恰好为0
5.还必须要考虑时间复杂度的影响,从下面两个因素进行改进
首先将所有子木棍进行排序
a.如果当前所采用的子木棍是作为拼接木棍的第一个而失败,那么这个试探就可以终止,肯定不会成功。因为假如可行那么每一个木棍(当然包括第一个)一定会用得到。
b.如果当前所采用的木棍时作为拼接木棍的最后一个而失败,也终止。因为这根木棍可以用后面更短的进行拼接,效果一致。
代码:
#include<iostream>
#include<fstream>
#include<algorithm>
using namespace std;
int num;
int len[100];
int used[100];
bool compare(const int argv1,const int argv2)
{
return argv1>argv2;
}
bool makeup(int n,int l,int sl)
{
if(n==0&&sl==0)
{
return true;
}
if(sl==0)
{
sl=l;
}
if(n>0)
{
int i=0;
for(i=0;i<num;i++)
{
if(used[i]!=0||sl<len[i])
continue;
used[i]=1;
if(makeup(n-1,l,sl-len[i]))
return true;
used[i]=0;
if(len[i] == sl||sl == l) break;
}
}
return false;
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
cin>>num;
while(num>0)
{
int sum=0;
for(int i=0;i<num;i++)
{
cin>>len[i];
sum+=len[i];
used[i]=0;
}
sort(len,len+num,compare);
for(int i=len[0];i<=sum;i++)
{
if(sum%i==0)
{
if(makeup(num,i,i))
{
cout<<i<<endl;
break;
}
}
}
cin>>num;
}
}
给一个详细解题的参考链接:
本文解析了一道关于如何通过算法找出最短原始木棍长度的问题。输入为多组已切分木棍的长度数据,需计算并输出原始木棍的最短可能长度。文章提供了详细的解题思路及C++代码实现。

被折叠的 条评论
为什么被折叠?



