约瑟夫环问题的描述为,设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。当任意给定n和m后,设计算法求n个人出圈的次序。
解题思路: 网上给的较多的解法是循环链表和数学推导出公式的思想,但如果是一个刚接触C语言没多久的人,对循环链表的解法肯定看不懂,而数学推导的过程相信也会让很多人特别迷惑,而用数组求解还是比较容易理解的。
用数组求解的基本思想就是用一个一维数组去标识这n个人的状态,默认全为1,也就是都在圈子内,当喊道m的人出圈之后,他的标识则变为0(就是出圈了),同时报数器清0,下一个人要从1开始。在每次报数之前要判断他是否在圈子内(也就是他的标识是否为1),如果在圈子里面才会继续报数。定义一个变量记录出圈的人数, 出圈的人数等于 n-1时,则游戏结束。
注意:当m = 1的时候,如果没有if(count == m - 1) break; 的判断,会把1到n都输出出来。
1 #include<stdio.h> 2 #define N 1000000 3 int flag[N] = {0}; 4 int main() 5 { 6 int n = 0, m = 0; 7 scanf("%d%d", &n, &m); 8 int i = 0; 9 int count = 0; //记录出圈的人数 10 int num = 0; //报数器 11 for(i = 1; i <= n; i++) { 12 flag[i] = 1; 13 } 14 while(count < n - 1) { 15 for(i = 1; i <= n; i++ ) { 16 if (1 == flag[i]) { 17 num++; 18 if(num == m) { 19 printf("%d\n", i); 20 count++; 21 flag[i] = 0; 22 num = 0; 23 } 24 if(count == n - 1) { 25 break; 26 } 27 } 28 29 } 30 } 31 32 33 for(i = 1; i <= n; i++) { 34 if(1 == flag[i]) { 35 printf("The last one is : %d\n", i); 36 } 37 } 38 39 40 return 0; 41 }