C++ 約瑟夫(Josephus)問題
阿新 • • 發佈:2019-01-07
一、題目:約瑟夫問題: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; }