約瑟夫問題

來源: POJ

總時間限制: 1000ms 內存限制: 65536kB

  • 描述
    約瑟夫問題:有n只猴子,按順時針方向圍成一圈選大王(編號從1到n),從第1號開始報數,一直數到m,數到m的猴子退出圈外,剩下的猴子再接着從1開始報數。就這樣,直到圈內只剩下一隻猴子時,這個猴子就是猴王,編程求輸入n,m後,輸出最後猴王的編號。

  • 輸入
    每行是用空格分開的兩個整數,第一個是 n, 第二個是 m ( 0 < m,n <=300)。最後一行是:

    0 0

  • 輸出
    對於每行輸入數據(最後一行除外),輸出數據也是一行,即最後猴王的編號

  • 樣例輸入

    6 2
    12 4
    8 3
    0 0

  • 樣例輸出

    5
    1
    7

參考代碼:

#include<iostream>
using namespace std;

//一共最多有300只猴子
int succedent[300]; //這個數組用於保存一個猴子後一位是誰,
      //比如“next[5]的值是7”就是說5號猴子的下一位是7號猴子,6號猴子已經在之前退出了。
int precedent[300];//這個數組用於保存一個猴子前一位是誰,用法和上面的類似。

int main() {
  int n, m;
  while (true) {
    cin >> n >> m;
    if (n == 0 && m == 0)
      break;
    for (int i = 0; i < n - 1; i++) {
      succedent[i] = i + 1;
      precedent[i + 1] = i;
    }
    succedent[n - 1] = 0;
    precedent[0] = n - 1;

    int current = 0;
    while (true) {
      //如果一共要報m次號,那麼取m-1次succedent之後就是需要退出的那隻猴子
      for (int count = 0; count < m-1; count++)
        current = succedent[current];

      int pre = precedent[current];
      int suc = succedent[current];
      //讓current號猴子退出很簡單,就是把前一位的“下一位”指向current的下一位,
      //下一位的“前一位”指向current的前一位就好了
      succedent[pre] = suc;
      precedent[suc] = pre;
      if (pre == suc) {
        //如果只剩下兩個了,那麼每個人的前位和後位就是同一個了。
        //current是退出的,那麼另一個就是剩下的。
        //我們的序號是從0編號的,輸出時要加一
        cout << pre+1 << endl;
        break;
      }
      current = suc;
    }
  }
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章