Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。于是决定了自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。然后下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
#include <stdio.h>
#define N 1000 //为计算的上限值
/*
2020-10-15
Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。于是决定了自杀
方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。然后下一个重新报数,直到所有人都自杀身亡
为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是
逃过了这场死亡游戏。
说明:输入需要计算的总人数n,通过数组来装对应的数字,每第三个就将对应值清零,当到最后一个值时,将已经清零的数组去掉,
每去掉一个数字,总数n减1。当全部排好后,再进行重复计算,直至n小于3时退出。
变量声明:i,j用于循环 ,zhi用于指向计数,即1,2,3,当等于3时就自杀,sign用于指向最后一个数时的标志位,
pai[i]用于存放序号的数组,n为计算的人数
*/
void main() {
int n,i,j,zhi=0,sign = 0;
int pai[N];
printf("请输入多少个人,小于%d\n",N); //需要计算多少人
scanf_s("%d", &n);
//将序号写入
for (i = 0; i < n; i++)
pai[i] = i + 1;
//去除
for (i = 0; i < n; i++)
{
if (n < 3) //退出条件
break;
zhi++; //循环一次指向加1
if (sign == 1) //用于指向最后时,将i重置为0,因为即使最后i已经赋回0,但回到for循环时,i又会回到1,所以需要这步
{
i = 0;
sign = 0;
}
if (zhi==3 && pai[i] != 0) //当标志为3时,把当前指向的数组清0
{
pai[i] = 0;
zhi = 0;
}
if ((i == n - 1) && n >= 3) //此时指向最后一个数,且总数大于等于3
{
for (i = 0; i < n; i++) //循环找出是0的数,去掉
{
if ((pai[i] == 0)&& (i!=n-1))
{
for (j = i; j < n - 1; j++) //将0的位置去掉,然后数组前移
pai[j] = pai[j + 1];
n = n - 1; //每去掉一个,总数-1
}
if ((pai[i] == 0) && (i == n - 1)) //若最后一个等于0,那么直接总数减1;
{
n = n - 1;
}
}
sign = 1; //走完最后的标志位
i = 0;
}
}
printf("最后活下来的是%d %d", pai[0], pai[1]);
}