快轉到主要內容

CSES-2162 Josephus Problem I

目錄


題目連結:https://cses.fi/problemset/task/2162

題意
#

此為經典的「約瑟夫問題(Josephus Problem)」。
\( n \) 個人圍成一圈,編號為 1 到 \( n \)。
從 1 號開始報數,規則為「跳過一個人,淘汰下一個人」。
過程持續進行,直到所有人皆被淘汰為止。
需要依序輸出被淘汰的人的編號。

思路
#

由於 \( n \) 的範圍不大且淘汰規則固定為「跳過一、淘汰一」,可使用佇列(Queue)直接模擬報數過程。

初始時將 1 到 \( n \) 依序推入 Queue。
當 Queue 中尚有元素時,反覆執行以下兩個步驟:

  1. 跳過第一個人:將排頭移至 Queue 尾端(先 push 排頭,再將其 pop)。
  2. 淘汰第二個人:輸出此時的排頭編號,並將其移出 Queue(直接 pop)。

利用 Queue 模擬環狀結構,持續進行直到 Queue 為空,輸出的序列即為完整的淘汰順序。

程式碼
#

#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define fi first
#define se second
#define INF LONG_LONG_MAX/1000
#define WA() cin.tie(0)->sync_with_stdio(0)
#define all(x) (x).begin(), (x).end()
#define int long long
#define PII pair<int, int>

signed main() { WA();
    int n; cin >> n; 
    
    // 使用 Queue 來模擬圍成一圈的人
    queue<int> q;
    
    // 一開始把 1 ~ n 的人都依序排進隊伍裡
    for (int i = 1; i <= n; i++) q.push(i);
    
    // 若 Queue 中尚有未淘汰者,持續模擬
    while (q.size()) {
        // 第一個人跳過:移至隊伍尾端
        q.push(q.front()); 
        q.pop();
        
        // 第二個人淘汰:印出它的編號並移出隊伍
        cout << q.front() << ' '; 
        q.pop();
    }
}
Piau 的筆記本
作者
Piau 的筆記本
希望我寫下來的東西能夠長久的記在我的腦中