主题:求助,难题!!
liuzilong1998
[专家分:0] 发布于 2011-02-01 00:18:00
由于学校上网的人越来越多了,导致学校的网速变的越来越慢。
为了解决这个问题,学校想出了一个办法,就是减少学校的宿舍楼,其中一个园区内宿舍是围成一个圆的,每幢楼都有一个编号,从1到n,然后拆出的顺序是从第一幢开始拆,然后跳过m-1撞楼继续拆下一个,如果n=17并且m=5,拆除的顺序是 (1,6,11,16,5,12,2,9,17,10,4,15,14,3,8,13,7),7是最后一幢被拆除的楼。
现在要求你编写一道程序,给你n幢楼,求出最小的m,使得每次都是第2幢是最后被拆除的。
Input.
给你n(3<=n<=150)幢楼,输入以0为结束。
Output
输出最小的m
Sample Input
3
4
5
6
7
8
9
10
11
12
0
Sample Output
2
5
2
4
3
11
2
3
8
16
回复列表 (共3个回复)
沙发
Tennokare [专家分:80] 发布于 2011-02-20 21:02:00
好吧,.刚学几天pascal刚来这论坛的小菜来解此题.求加分!
可能不是最优解.
PROGRAM p79d;
VAR
a,b:ARRAY[1..150]OF integer;
n,i,j:integer;
FUNCTION assume(n0:integer):integer; {n0为输入的n的值参}
VAR
stop:boolean;
m,l,step:integer;
c:ARRAY[1..150]OF integer;
PROCEDURE find(m0:integer); {该过程判断m是否符合条件}
VAR
flag:boolean;
s,k:integer;
BEGIN
s:=0;
flag:=true; { 就是漏掉这里让我内牛满脸..}
REPEAT
FOR k:=2 TO n0 DO
BEGIN
IF c[k]=0 THEN continue;
s:=s+c[k];
IF s=m0
THEN BEGIN
IF (k=2)
THEN IF step=1 {判断2是不是最后被拆}
THEN BEGIN stop:=false;exit END {是,则m是正解,跳出该函数}
ELSE BEGIN flag:=false;break END; {不是,跳出循环}
c[k]:=0;
s:=0;
dec(step)
END
END
UNTIL flag=false {flag的作用你懂的..}
END;
BEGIN
m:=1;
stop:=true; {stop的作用,m不是正解就控制循环把m递增}
WHILE stop DO
BEGIN
inc(m);
FOR l:=2 TO n0 DO
c[l]:=1;
step:=n0-1;
find(m);
END;
assume:=m {找到正解了,就把m赋值给函数assume}
END;
BEGIN
readln(n);
i:=0; {i的作用..判断读取了多少个数n,后面需要用}
WHILE n<>0 DO {这里看不懂的话就忽略全文吧.. =.=||}
BEGIN
inc(i);
a[i]:=n;
readln(n)
END;
FOR j:=1 TO i DO
BEGIN
b[j]:=assume(a[j]);
writeln(b[j])
END
END.
板凳
Tennokare [专家分:80] 发布于 2011-02-20 21:04:00
还是我..
调试这个不容易吖,那个flag控制被我完美的忽略了..
搞了半天计算姬还是陷入了死循环..
后来才捉出这个小样flag. 设置为true后大功告成.!
3 楼
Tennokare [专家分:80] 发布于 2011-02-20 21:27:00
再补充..
其实这条题就是约瑟夫问题的变种.
如果不知道约瑟夫..
那么恭喜你,忽略此题吧.
这条题目的设置. 我不想吐槽了..
上网人太多,就拆宿舍楼.. 真有喜感... 但愿楼主住在2号宿舍..
我来回复