约瑟夫问题

来源:互联网 发布:营销推广案例 知乎 编辑:程序博客网 时间:2024/05/21 07:09
著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到剩余一个人为止。一开始要站在什么地方才能避免被处决?
     解决思路:
     建立一个有40个元素的数组, 将元素的初值赋为1,第一个元素从1开始计数,凡是遇到计数值为3的倍数的元素,将其值赋为0,遍历结束后从数组首元素接着计数......直到数组中只有一个为值1 的元素为止,其下标加1,即为最后幸存者
#include <stdio.h>#define N   41  //总人数#define NUM 3   //出局的数字void print (int *a, int n){int i;for (i = 0;i < n; i++){printf ("%2d",a[i]);}putchar ('\n');}/*  将所有人的值编为1,出局的的人编为0,直到只有一个1为止*/void Joseph (int *a){int temp = 0;   //报数    int count = N;  //当前剩余1的数量    while (1){int i;//遍历报数,超出总人数则第一个人接着报数for (i = 0;i < N; i++)  {if (a[i] == 0)   //遇到出局的人跳过报数{continue;   }temp++;if (temp % NUM == 0)   //判断是否出局,若出局值编为0{count--;a[i] = 0;}}if (count == 1)    //剩余一人结束报数break;}}int main (){printf ("Function : Joesphus.\n");int a[N] = {};int i;for (i = 0;i < N; i++){a[i] = 1;}print (a,sizeof(a)/sizeof(a[0]));Joseph (a);print (a,sizeof(a)/sizeof(a[0]));for (i = 0;i < N; i++){if (a[i] == 1){printf ("Winner is %d !\n", i+1);  //数组下标从0开始,所以第n个元素是第n+1个人的序号}}return 0;}

原创粉丝点击