題目出處:洛谷 p1996 ,略有修改。
題目描述
約瑟夫問題是乙個非常經典的問題。
n個人(n<=100)圍成一圈,從第乙個人開始報數,數到m的人出列,再由下乙個人重新從1開始報數,數到m的人再出圈,……依次類推,直到所有的人都出圈,請輸出依次出圈人的編號。
輸入格式
輸入一行包含兩個正數 \(n\) 和 \(m\) ,以乙個空格分隔 \(1 \le n,m \le 100\) 。
輸出格式
輸出依次出圈人的編號,兩兩之間有乙個空格分隔(最後沒有空格,可參見樣例)。
樣例輸入
10 3
樣例輸出3 6 9 2 7 1 8 5 10 4
題目分析如下
解法一:陣列模擬
這種方法是最原始最暴力的一種解法,首先,在知道 \(n\) 和 \(m\) 的前提下,我們開乙個陣列 \(out\) , \(out[i]\) 用於表示第 \(i\) 個人是否已經離開了這個環, \(out[i] = true\) 表示這個人已經出去了; \(out[i] = false\) 表示這個人還在環裡面。
一開始所有的 \(out[i]\) 都為 false,因為一開始大家都在環裡面。
同時我開乙個變數 \(id\) 用於表示當前報數的人的編號,一開始 \(id = 1\) 。
然後我迴圈 \(n\) 輪(每一輪肯定會出環乙個人),每一輪開始時我要初始化乙個變數 \(cnt = 0\) ,用於表示當前已經報數的人的數量。
然後接下來我就遍歷 \(id\) ,如果 \(out[i] == true\) (說明第 \(id\) 個人當前沒有出環),那麼計數 \(cnt++\) 。
如果此時 \(cnt == m\) ,說明已經報數累計了 \(m\) 人次,我只需要輸出 \(id\) ,同時令 \(out[id] = true\) 即可(說明第 \(id\) 個人已經出去了),然後結束該輪。
否則, \(id ++\) ,如果 \(id > n\) ,則令 \(id = 1\)(因為是環,所以第 \(n\) 個人報完數之後,又會回到第 \(1\) 個人繼續報數)。
實現**如下:
#include using namespace std;
const int maxn = 110;
bool out[maxn];
int n, m;
int main()
id ++;
if (id > n) id = 1;
}if (i) putchar(' ');
out[id] = true; // 第id個人出環
cout << id;
}cout << endl;
return 0;
}
解法二:佇列模擬
因為大家可能都用過stl提供給我們的模擬佇列的queue,所以這裡再講解一下使用queue來模擬約瑟夫環問題的方法。
使用佇列來模擬約瑟夫環問題的解題思路如下:
首先將 1 到 n 這 n 個元素一次入隊。
接下來進行 n-1 輪,每輪先迴圈 m-1 次,每次將隊首元素pop出來的同時在push進隊尾,這 m-1次迴圈之後的隊首元素就是報 m 個那個人的編號,輸出隊首元素,然後將隊首元素pop出佇列(這個元素就不用再push進佇列了)。
n-1 輪之後,佇列中只剩下了乙個人,就是我們的隊首元素,我們只需要輸出它,我們的1程式就可以結束了。
實現**如下:
#include using namespace std;
int n, m;
queueque;
int main()
cout << que.front() << " ";
que.pop(); // 第m個報數的人出去
}cout << que.front() << endl; // 最後佇列中只有乙個人
return 0;
}
不過這裡大家要注意的是,老師的資料是沒有問題的,但是洛谷原題的資料是有問題的,老師的這個程式在洛谷上面第3組測試樣例沒過,後來看了半天才發現原來第3組資料的輸入是「0 0」,所以如果你要使用這個**去提交到洛谷的話記得 \(n = 0\) 的時候要特殊判斷。 搜尋入門練習題5 八皇后問題 題解
題目描述 輸出格式 輸出乙個整數,用於表示八皇后問題的放置方案。題目分析 首先我們用 x,y 來表示棋盤上第 x 行第 y 列的格仔的座標。那麼,兩個皇后 x 1,y 1 和 x 2,y 2 會互相攻擊當且僅當滿足如下條件之一 我們可以用深度優先搜尋來解決這道題。我們可以發現的是,要想在 8 tim...
基礎練習題解
1.矩形相交面積 問題描述 平面上有兩個矩形,它們的邊平行於直角座標系的x軸或y軸。對於每個矩形,我們給出它的一對相對頂點的座標,請你程式設計算出兩個矩形的交的面積。輸入格式 輸入僅包含兩行,每行描述乙個矩形。在每行中,給出矩形的一對相對頂點的座標,每個點的座標都用兩個絕對值不超過10 7的實數表示...
9 3練習題5 單詞覆蓋還原 題解
題目出處 洛谷 p1321 題目描述 乙個長度為 l 3 le l le 255 的字串中被反覆貼有boy和girl兩單詞,後貼上的可能覆蓋已貼上的單詞 沒有被覆蓋的用句點表示 最終每個單詞至少有乙個字元沒有被覆蓋。問貼有幾個 boy 幾個 girl?輸入格式 一行被被反覆貼有boy和girl兩單詞...