寻求高效算法:Come in,Please!

BUF 2002-05-15 04:54:14
Problem:

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 zero.

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

Chinese:
有若干段长度一样的棍子,被随机的截成一些小段,告诉你这些小棍子的长度,请问原来这些长度一样的棍子的长度最小的可能是多少?
输入: 小棍子的个数 和 各自的长度
输出: 原棍子长度的最小可能值

希望各位给出高效的算法!! thanx!
...全文
50 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
penu 2002-06-24
  • 打赏
  • 举报
回复
对不起,刚才不小心按到“发出回复”。
重写算法部分:
int i,t;
if (Num==1) //为素数
return(0) //无解
else
for(i=0;i<Num;i++)
{
t=X/YinZi[i];
…… //用类背包问题算法将x1、x2、……、xn分成YinZi[i]份,每份总长为t;如果成功,return(t)。
}
return(0) //无解

注:以上为原题的解答。
penu 2002-06-24
  • 打赏
  • 举报
回复
假设有n根小棍,从大到小排列它们的长度为:x1、x2、……、xn;
令X=x1+x2+……+xn,将X因式分解,并将其因子(不含1及重复)按从大到小存入数组YinZi[](下标从0开始),不重复因子数为Num。
有:
1、x1是原木棍长度的下限值。
2、必定存在i,0<=i<Num,使得原木棍长度为X/YinZi[i]。即X/YinZi[Num-1]是原木棍长度的上限值。
3、算法:
int i,
if (Num==1) //为素数
return(0) //无解
else
for(i=0;i<Num;i++)
intfree 2002-06-24
  • 打赏
  • 举报
回复
以前我们做深度优先搜索的练习题,有很多剪枝可以用。
oknet 2002-06-24
  • 打赏
  • 举报
回复
把问题倒过来!

现在需要 长度为 a1, a2 , a3, a4 ,a5 的木棍各 n1,n2,n3,n4,n5根

目前有 M 长度的原材料数根,问最少需要 M 长度的原材料多少根?

明显的是求最优化的问题,用单纯形喽。
BUF 2002-06-20
  • 打赏
  • 举报
回复
Here is my codes, Can you tell me where the bugs are or give me some test cases?
================================================================
#include <iostream.h>
#include <memory.h>
#include <math.h>
#include <stdlib.h>
#define fin cin

int num[100] , len[1000] , k;
int n_len[100] , temp[100] , n , sum;

bool getcheck(int cur_len , int last_id)
{
int i(last_id);
for (;;) {
while ( (!temp[i] || cur_len < i) && i>0 ) {
i --;
}
if ( i==0 ) return false;
temp[i] --;
if ( cur_len==i ) {
return true;
}
if ( getcheck(cur_len - i , i) ) return true;
temp[i] ++;
i --;
}
}

int fun(const void * p1,const void * p2)
{
int * a = (int *)p1;
int * b = (int *)p2;
return *a - *b;
}
void main()
{
int i , j;
fin >> n;
while ( n > 0 ) {
k = 0;
memset(n_len , 0 , sizeof(n_len));
sum = 0;
int max(0);
for (i = 0;i < n;i ++) {
fin >> num[i];
n_len[num[i]] ++;
sum += num[i];
if ( max < num[i] ) max = num[i];
}
int en;
en = sqrt(sum);
for (i = 1;i <= en;i ++) {
if ( sum % i == 0 ) {
if ( i >= max ) {
len[k++] = i;
}
if ( sum / i >= max ) {
len[k++] = sum / i;
}
}
}
qsort((void *)len,k,sizeof(int),fun);
int end;
for (i = 0;i < k;i ++) {
for (j = 1;j <= max;j ++) {
temp[j] = n_len[j];
}
end = sum / len[i];
for (j = 0;j < end;j ++) {
if ( !getcheck(len[i] , max) ) break;
}
if ( j == end ) {
cout << len[i] << endl;
break;
}
}
fin>>n;
}
}
===================================================================
Waiting...............
starfish 2002-05-17
  • 打赏
  • 举报
回复
如果知道了原来每根棍子的长度x,然后再输入数据个定的棍子中找到是否可以构成长度为x的棍子的过程是一个动态规划的过程,类似于背包问题。具体而言,输入数据中每个棍子的长度相当于每样物品的重量,背包的总容量为x,要求放入尽量多的物品,你只要利用类似背包问题的动态规划就可以求出如何组合输入数据中的棍子得到长度为x的棍子;然后重复这个过程,直到输入数据中所有的棍子都被用完,得到若干个长度为x的棍子。如果这一过程进行不下去,说明原来棍子长度为x并不能符合题意,于是改变原来棍子的长度,继续这一过程。这样复杂度就应该不大了吧
BUF 2002-05-16
  • 打赏
  • 举报
回复
复杂度不大吗? 我不敢苟同,还是倾向于 BFS 或 DP ,但始终没有好的想法
wait....
BUF 2002-05-16
  • 打赏
  • 举报
回复
Sorry! 我也是这么想的,先预处理,再搜索,
But, I`v got n Time Exceeded. :(
Wait for more effective algorism.........
BUF 2002-05-16
  • 打赏
  • 举报
回复
好像不对吧:
i.e. input:
5
1 2 3 4
如你的算法;
n = 4 N = 10 Lmax = 4
则:
4 5 6 7 8 9 10
x[1] * * * * * *  * x[1] = 6
x[2] * * * * x[2] = 4
x[3] * * x[3] = 2
x[4] * * x[4] = 2
应得到 5 ,但这样是得不到5的

是不是我搞错了?
systree 2002-05-16
  • 打赏
  • 举报
回复
由于计算机乘法比除法快几十倍,所以我提供如下算法:
1:求所有n个棍长度之和N,求最长的棍Lmax
2:分配内存int x = new int[n],并初试化为全零
3:从第一个棍起(长l1),从Lmax到N扫描,是l1的倍数的就将x中该项加1
4:扫描完成后,从Lmax到N扫描x,找到第一个等于n的位置就可以

另外,可以继续优化,比如
a.找到最短的Lmin,然后只分配(N+Lmin-1)/Lmin个int
b.分段扫描等
BUF 2002-05-16
  • 打赏
  • 举报
回复
BFS 似乎也超时,如果没有好的优化的话
starfish 2002-05-15
  • 打赏
  • 举报
回复
耶, 原来 1+1 也在呀
starfish 2002-05-15
  • 打赏
  • 举报
回复

如果一共有n条小棍子,先求出他们总长度L,然后假设原来的棍子有x条,这里x=n, n-1, .., 1。于是原来每根棍子长度为 t=L/x。然后只要验证输入数据中的那些小棍子是否可以构成x个长度为t的棍子即可,这一步的验证可以将棍子从长到短排序后用搜索来验证,因为确定了原来每根棍子的长度x,所以这个验证过程的复杂度应该不会太大。而x的值只要循环进行穷举即可。
one_add_one 2002-05-15
  • 打赏
  • 举报
回复
你把所有的小棍子的长度加起来得到一个总和N。

然后再从小到大求N的所有因子。

然后再广度搜索,检查这个因子是否符合情况。

这样应该是比较优化的算法。

但感觉这题可以用DP做,现在还没想出来:(
BUF 2002-05-15
  • 打赏
  • 举报
回复
wait.....

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧