题目编号 :Exp04-Enhance02,GJBook3-06-26
题目名称:约瑟夫问题(Josephus)
题目描述:
古代某法官要判决 n 个犯人死刑, 他有一条荒唐的逻辑, 将犯人首尾相接排成圆圈,所有计数从1开始; 然后从第 s 个人开始数, 每数到第 m 个犯人,则拉出来处决; 然后再数 m 个,数到的犯人再处决;... ; 但剩下的最后一个犯人可以赦免。编程序,给出处决顺序,并告知哪一个人活下来。
输入:三个正整数 n(≤1000),s和m,都可以使用int类型变量表示。
输出:依次输出被处决人员的编号,每个编号之间用一个西文空格间隔,最后一个编号后无字符。
样例:
输入:6 1 5
输出:5 4 6 2 3 1
#include <stdio.h>
int main() {
int n, s, m, a[1000]; //n个犯人,从s开始数,每次数到m的杀掉
scanf_s("%d %d %d", &n, &s,&m);
int i,j;
int x=s-1,cnt = 0;
for (i = 0; i <= n - 1; i++) {
a[i] = i;
}
while (cnt <= n - 2) { //若无格式要求,此处可写成cnt<=n-1,直接输出所有编号
x = (x - 1+m) % (n-cnt);
printf("%d ", a[x] + 1); //由于是从a[0]开始存放0,所以每次选中的号码为下标+1。
a[x] = -1;
j = 0; //每处置一个人后,需要将剩余人重新放入数组,从0开始放,每次将j置0
for(i=0;i<=n-1-cnt;i++)
if (a[i] != -1) {
a[j] = a[i];
j++;
}
cnt++;
}
j--;
printf("%d", a[j] + 1);
return 0;
}
以上代码是采用的从a[0]开始存放0,即元素等于下标,相当于把每个犯人的编号-1后存放,故输出时要+1.
如果从a[0]开始存放编号1,则直接输出。
如果从a[1]开始存放1,(a[0]在题中无意义),则需注意:1.取余的特殊情况,由于a[0]不存在,下标x取到零时需将x赋值n-cnt。2.输出最后一个编号时,数组中仅剩一个元素a[1],任何正整数%1=0,a[0]无意义,因此最后一个号码需单独输出