博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

猴子选大王

Posted on 2010-10-19 15:21  桃子在路上  阅读(1527)  评论(0编辑  收藏  举报

【问题】n只猴子选大王,选举办法如下:从头到尾1,2,3报数,凡报3的退出,余下的从尾到头1,2,3报数,凡报3的退出...如此类推,当剩下两只猴子时,取这时报1的为王,若想当猴王,请问当初应占据什么位置?

【测试数据】

n │ 7 │ 10│20│100 │

位置│2 │ 8│16│ 77 │

【参考程序1】

const number=3;

var n,num,i,total:integer;

a:array[1..100]of boolean; order:boolean;

begin

writeln('input n:');

readln(n);

total:=n; {队伍中剩下的猴子数}

for i:=1 to n do a[i]:=true;

repeat

order:=true; {order=true:顺序报数}

num:=0; {num:报的数字}

for i:=1 to n do {顺序报数}

if a[i] then begin {第i只在队列中才有资格报数}

num:=num+1;

if (num=number) then begin {如果为3}

a[i]:=false;total:=total-1; {出队,且猴子数少1}

num:=0; {num置0,又准备从1报起}

end;

end; {报到尾}

if total>number-1 then order:=false; {如还要继续报,则从尾到头}

num:=0; {从尾到头时,order=false}

for i:=n downto 1 do {逆向报数}

if a[i] then begin {在队列中}

num:=num+1;

if (num=number) then begin

a[i]:=false;total:=total-1;

num:=0;

end;

end;

until total=number-1; {直到剩下2只}

if not order then for i:=1 to n do if a[i] then begin

{报剩2只时,如上一次为从尾到头报数,则猴王为从头到尾报的第一只}

writeln('The Monkey King is :',i);readln;halt;end;

if order then for i:=n downto 1 do if a[i] then begin

{报剩2只时,如上一次为从头到尾报数,则猴王为从尾到头报的第一只}

writeln('The Monkey King is :',i);readln;halt;end;

end.

 

【参考程序2】 程序1中,用了order来记录是顺序还是逆序报数,不太方便。现简化之,取消了order,而在每一次报数前都判断是否只剩2只。

const number=3;

var n,num,i,total:integer; a:array[1..200]of boolean;

begin

writeln('input n:');

readln(n);

total:=n;

for i:=1 to n do a[i]:=true;

repeat

num:=0;

for i:=1 to n do

if a[i] then begin

if total=2 then begin writeln('he is :',i); readln;halt;end;

num:=num+1;

if (num=number) then begin

a[i]:=false;total:=total-1;

num:=0;

end;

end;

num:=0;

for i:=n downto 1 do

if a[i] then begin

if total=2 then begin writeln('he is :',i); readln; halt;end;

num:=num+1;

if (num=number) then begin

a[i]:=false;total:=total-1;

num:=0;

end;

end;

until total<number-1;

end.