回 帖 发 新 帖 刷新版面

主题:求助,难题!!

由于学校上网的人越来越多了,导致学校的网速变的越来越慢。
为了解决这个问题,学校想出了一个办法,就是减少学校的宿舍楼,其中一个园区内宿舍是围成一个圆的,每幢楼都有一个编号,从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个回复)

沙发

好吧,.刚学几天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.

板凳

还是我..
调试这个不容易吖,那个flag控制被我完美的忽略了..
搞了半天计算姬还是陷入了死循环..

后来才捉出这个小样flag. 设置为true后大功告成.!

3 楼

再补充..
其实这条题就是约瑟夫问题的变种.
如果不知道约瑟夫..
那么恭喜你,忽略此题吧.

这条题目的设置. 我不想吐槽了.. 

上网人太多,就拆宿舍楼.. 真有喜感... 但愿楼主住在2号宿舍..

我来回复

您尚未登录,请登录后再回复。点此登录或注册