1. 程式人生 > >C++ 約瑟夫(Josephus)問題

C++ 約瑟夫(Josephus)問題

一、題目:約瑟夫問題:n個人圍成一桌,數到m的人出列

 

二、實現方法1: 每出列一個,就往前移動陣列,用求餘解決到尾問題

// 每出列一個,就往前移動陣列
// 用求餘解決到尾問題
#include <iostream>

void JosePhus(int n, int m, int start) {
    int i, *arr = new int[n]; // 動態分配陣列
    int count; // 儲存當前已站出來的人數
    
    for(i = 0;i < n; i++) // 初始化,把各位置號存入陣列中
        arr[i] = i + 1;
    count = 1;
    start--; // 因為陣列下標從0開始,所以要減1
    while(count < n) { // 當前已站出來的人數
        std::cout << arr[start] << ","; // 輸出當前要站出來的人的位置號
        for(i = start; i < (n - count); i++)
            arr[i] = arr[i+1]; // 把位置號前移
        
        // start + m - 1:減1是因為該位置號的人已出列,位置號前移了一位
        // n - count: 當前剩下的人數
        start = (start + m - 1) % (n - count); // 考慮到尾了,要從頭開始,所以用取餘,或者用判斷方法
        
        count++;
    }
    std::cout << arr[0] << "\n";
}

int main(int argc, const char * argv[]) {
    // insert code here...
    int n, m, start; // n:人數  m:數到多少出列  start:開始位置
    
    std::cout << "請輸入n,m,start:\n";
    while(std::cin >> n >> m >> start) {
        JosePhus(n, m, start); // 呼叫解決約瑟夫問題的函式
        std::cout << "請輸入n,m,start:\n";
    }
    return 0;
}

執行結果:

、實現方法2不移動陣列:將陣列該位置已出列的設為零

//  不移動陣列:將陣列該位置已出列的設為零
//  總結:(1)移動陣列:將位置號前移,會耗費很多時間
//       (2)不移動陣列:當剩下的人數較少時,找不為0的會耗費很多時間
#include <iostream>

void JosePhus(int n, int m, int start) {
    int i, *arr = new int[n]; // 動態分配陣列
    int count; // 儲存當前已站出來的人數
    
    for(i = 0;i < n; i++) // 初始化,把各位置號存入陣列中
        arr[i] = i + 1;
    count = 1;
    start--; // 因為陣列下標從0開始,所以要減1
    int mCount; // 記錄數了多少
    while(count < n) { // 當前已站出來的人數
        std::cout << arr[start] << ","; // 輸出當前要站出來的人的位置號
        arr[start] = 0; // 將當前要出列的位置號設為0
        mCount = 0;
        // 從start開始數
        while(mCount < m) {
            if(start == 7) // 條件判斷:是否已到陣列尾
                start = 0;
            else
                start++; // 往後移
            if(arr[start] > 0) { // 不為0,還沒出列
                mCount++;
            }
        }
        count++;
    }
    for(i = 0; i < n; i++) { // 輸出最後一個人
        if(arr[i] > 0) {
            std::cout << arr[i] << "\n";
            break;
        }
    }
}

int main(int argc, const char * argv[]) {
    // insert code here...
    int n, m, start; // n:人數  m:數到多少出列  start:開始位置
    
    std::cout << "請輸入n,m,start:\n";
    while(std::cin >> n >> m >> start) {
        JosePhus(n, m, start); // 呼叫解決約瑟夫問題的函式
        std::cout << "請輸入n,m,start:\n";
    }
    return 0;
}