新约瑟夫问题
【问题描述】(newnumber.pas/c/cpp)
将1~M这M个自然数按由小到大的顺序沿顺时针围成一圈。以S为起点,先沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,再沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,……。这样按顺时针方向和逆时针方向不断出圈,直到全部数出完圈为止。打印先后出圈的数的序列0。
【输入格式】newnumber.in
文件中共4行,每行为1个自然数,分别表示题目中的M,S,N,K。M不超过1000。
【输出格式】newnumber.out
仅一行,先后出圈的序列,每个数字之间有一个空格。
【样例输入】
8
1
3
2
【样例输出】
3 1 5 2 7 4 6 8
(解释:先从1开始沿顺时针方向数到3,所以3先出圈;再从2开始沿逆时针方向数到1,所以1出圈;再从2开始沿顺时针方向数到5,所以5出圈;再从4开始沿逆时针方向数到2,所以2出圈,……)
代码
type
xx=record
l,r:integer;
end;
var m,s,n,k,i,j,sum:integer;
a:array [1..1000] of xx;
begin
assign(input,'newnumber.in'); reset(input);
assign(output,'newnumber.out'); rewrite(output);
readln(m);
readln(s);
readln(n);
readln(k);
for i:=2 to m-1 do {做好链表,每个元素的左右相邻位置}
begin
a[i].l:=i-1;
a[i].r:=i+1;
end;
a[1].l:=m;a[1].r:=2;{特殊情况}
a[m].l:=m-1;a[m].r:=1;
sum:=m;{计数}
j:=a[s].l;{指针元素位置}
while sum>0 do
begin
for i:=1 to n do {右移}
j:=a[j].r;
if sum=1 then write(j) else write(j,' ');
a[a[j].l].r:=a[j].r;{改变链表,注意a[a[j].l].r的运用}
a[a[j].r].l:=a[j].l;
sum:=sum-1; if sum=0 then exit;
for i:=1 to k do{左移}
j:=a[j].l;
if sum=1 then write(j) else write(j,' ');
a[a[j].l].r:=a[j].r;
a[a[j].r].l:=a[j].l;
sum:=sum-1;
end;
close(input); close(output);
end.
xx=record
l,r:integer;
end;
var m,s,n,k,i,j,sum:integer;
a:array [1..1000] of xx;
begin
assign(input,'newnumber.in'); reset(input);
assign(output,'newnumber.out'); rewrite(output);
readln(m);
readln(s);
readln(n);
readln(k);
for i:=2 to m-1 do {做好链表,每个元素的左右相邻位置}
begin
a[i].l:=i-1;
a[i].r:=i+1;
end;
a[1].l:=m;a[1].r:=2;{特殊情况}
a[m].l:=m-1;a[m].r:=1;
sum:=m;{计数}
j:=a[s].l;{指针元素位置}
while sum>0 do
begin
for i:=1 to n do {右移}
j:=a[j].r;
if sum=1 then write(j) else write(j,' ');
a[a[j].l].r:=a[j].r;{改变链表,注意a[a[j].l].r的运用}
a[a[j].r].l:=a[j].l;
sum:=sum-1; if sum=0 then exit;
for i:=1 to k do{左移}
j:=a[j].l;
if sum=1 then write(j) else write(j,' ');
a[a[j].l].r:=a[j].r;
a[a[j].r].l:=a[j].l;
sum:=sum-1;
end;
close(input); close(output);
end.