example 4-3
本题是一个简单的约瑟夫问题的变形,其中最为精妙的代码便是 go 函数里的那个 do-while 语句,它使得可以按顺时针或逆时针方向不断地加一减一,直到遇到没有被点名的人,代码如下:
#include <stdio.h>
#define maxn 25
int n, k, m, a[maxn];
int go(int p, int d, int t)
{
while (t--)
{
do {
p = (p+d+n-1) % n + 1;//如若d为正负一,那么这条指令会顺时针或逆时针的加一
}
while (a[p] == 0);//若已被点到,那么就继续向前,相当于没有这个人
}
return p;
}
int main(void)
{
int i;
while (scanf("%d%d%d", &n, &k, &m) && n)
{
for (i = 1; i <= n; i++) a[i] = i;
int left = n;//还剩下的人
int p1 = n, p2 = 1;
while (left)
{
p1 = go(p1, 1, k);
p2 = go(p2, -1, m);
printf("%3d", p1);
left--;
if (p2 != p1)
{
printf("%3d", p2);
left--;
}
a[p1] = a[p2] = 0;
if (left)
printf(",");
}
printf("\n");
}
return 0;
}