約瑟夫環問題的描述為,設有編號為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 }