有n 只猴子选大王,先从头至尾1 ... p 报数,报到p 的猴子退出;
报至尾后,再从尾至头继续报数(注意:如果报到尾时不是p,则反过来
报数仍然从尾开始,即尾部的这个猴子将连续被报2 个数),仍然是报到p
的猴子退出;报到头后,再从头继续,......;直至剩下最后1 个猴子,即
为选出的大王。
报至尾后,再从尾至头继续报数(注意:如果报到尾时不是p,则反过来
报数仍然从尾开始,即尾部的这个猴子将连续被报2 个数),仍然是报到p
的猴子退出;报到头后,再从头继续,......;直至剩下最后1 个猴子,即
为选出的大王。
Dim C As New Collection, i As Integer, p As Integer, n As Integer, forward As Boolean
p = Val(InputBox("请输入p值", , "9"))
n = Val(InputBox("请输入n值", , "10"))
If p < 1 Or n < 1 Then MsgBox "数据错误": Exit Sub
For i = 1 To n
C.Add i
Next i
i = 1: forward = True: n = C.Count
Do Until n = 1
i = i + IIf(forward, 1, -1) * (p Mod (n * 2) - 1)
Retry:
If i > n Then i = 2 * n - i + 1: forward = False: GoTo Retry
If i < 1 Then i = -i + 1: forward = True: GoTo Retry
C.Remove i
n = C.Count
i = i + IIf(forward, 0, -1)
If i > n Then i = n: forward = False
If i < 1 Then i = 1: forward = True
Loop
MsgBox "大王诞生:" & CStr(C.Item(1))
End Sub
Dim n As Integer
Dim p As Integer
Dim cm() As Integer
Dim cp As Integer
Dim bf As Boolean
Dim i As Integer
n = Val(Text1)
p = Val(Text2)
ReDim cm(n)
For i = 1 To n
cm(i) = i
Next i
cp = 0
bf = True
Do While n > 1
For i = 1 To p
If bf Then
cp = cp + 1
Else
cp = cp - 1
End If
If cp = n + 1 Then
bf = False
cp = n
ElseIf cp = 0 Then
bf = True
cp = 1
End If
Next i
For i = cp To n - 1
cm(i) = cm(i + 1)
Next i
n = n - 1
If bf = True Then cp = cp - 1
If cp = n And bf = True Then
cp = n + 1
bf = False
ElseIf cp = 1 And bf = False Then
cp = 0
bf = True
End If
Loop
Print cm(1)
End Sub
也有add方法,count属性吗?不会吧……呵呵
PROGRAM ex1_2_10(input,output);
TYPE
arr=array[ 1..100] of 0..1;
VAR
h :arr;{猴子是否在列的记录数组,1 为在列,0 为已出列}
i,m,n,p,f,s:byte;
PROCEDURE num(var n:byte);
begin
if n>1 then {递归终止条件为只剩1 个猴子}
begin
case i mod 2 of {判断是正方向还是反方向报数}
1:for f:=1 to m do {正方向报数处理}
if h[ f] <>0 then {只对在列的猴子进行处理}
begin
inc(s);{报数变量递增}
if s=p then begin {报到p 作以下处理}
s:=0;{报数计数重新开始}
dec(n);{猴子数减1}
h[ f] :=0 {该猴子清除出数组}
end
end;
0:for f:=m downto 1 do {反方向报数处理与正方向类似}
if h[ f] <>0 then
begin
inc(s);
if s=p then
begin s:=0;dec(n);h[ f] :=0 end
end
end;
inc(i);{i 是报数方向计数器,奇数为正向,偶数为反向}
num(n){用新的在列猴子数进入新的递归}
end
end;
BEGIN
write('Input n,p:');readln(n,p);
for i:=1 to n do h[ i] :=1;{猴子是否在列的记录数组置初值}
i:=1;{报数方向计数器置初值,表示正方向开始报数}
m:=n;{m 记录猴子总数,用于正反方向对全数组扫描,因为n 将变小}
s:=0;{报数计数器置初值}
num(n);{开始以猴子总数进入递归}
i:=1;while h[ i] =0 do inc(i);{找出在列的唯一一个猴子}
writeln('The leader is:',i){即选出的大王}
END.Pascal参考答案,这个递归也太...
arr=array[ 1..100] of 0..1;VAR
h :arr;{猴子是否在列的记录数组,1 为在列,0 为已出列}
i,m,n,p,f,s:byte;PROCEDURE num(var n:byte);
begin
if n>1 then {递归终止条件为只剩1 个猴子}
begin
case i mod 2 of {判断是正方向还是反方向报数}
1:
for f:=1 to m do {正方向报数处理}
if h[ f] <>0 then {只对在列的猴子进行处理}
begin
inc(s);{报数变量递增}
if s=p then begin {报到p 作以下处理}
s:=0;{报数计数重新开始}
dec(n);{猴子数减1}
h[ f] :=0 {该猴子清除出数组}
end
end;
0:
for f:=m downto 1 do {反方向报数处理与正方向类似}
if h[ f] <>0 then
begin
inc(s);
if s=p then
begin
s:=0;
dec(n);
h[ f] :=0
end
end
end;
inc(i);{i 是报数方向计数器,奇数为正向,偶数为反向}
num(n){用新的在列猴子数进入新的递归}
end
end;BEGIN
write('Input n,p:');readln(n,p);
for i:=1 to n do h[ i] :=1;{猴子是否在列的记录数组置初值}
i:=1;{报数方向计数器置初值,表示正方向开始报数}
m:=n;{m 记录猴子总数,用于正反方向对全数组扫描,因为n 将变小}
s:=0;{报数计数器置初值}
num(n);{开始以猴子总数进入递归}
i:=1;while h[ i] =0 do inc(i);{找出在列的唯一一个猴子}
writeln('The leader is:',i){即选出的大王}
END.看了一下,真是白x……这种递归……浪费堆栈~!