在一年半前還是個新生,第一次接觸專業的程式設計教育的我刷題刷的很起勁,經典的猴子選大王問題就是在那時候遇到的,那時候我花了好久,用陣列加判斷實現了模擬選人,最終做出來了這道題。
如今已經熟練了掌握各種容器,對程式設計的理解也不可同日而語,但模擬已經不能滿足如今的需要了。
好久以前老師曾助教新生時發現乙個孩子用了 「公式推導法」 卻說不出個所以然,於是讓我們來解釋,當時我絞盡腦汁沒有想明白,最後有幾個慧根靈光的同學說了說,感覺沒懂,於是不再深究。
直到前幾天做題又遇到了這個題,模擬時間超限,公式法又不會,於是等到比賽結束,開始用心的研究【約瑟夫環】了。
演算法講解
**展示
變 k 講解
推薦題目
鳴謝文章
基礎題意
像以上這些都是可以用約瑟夫環來解決的例題,這裡我只列了三個我想得起來的。
第乙個是基礎,第二個是應用,第三個是推廣。
思路簡介
這一類的題模擬的方法就不說了,基本上往後做 acm 用模擬肯定 tle 。
思路就是:【例如 10 只猴子裡選大王
具體怎麼轉換,接下來我們詳細講解一下轉換方式
首先搞清 10 個猴去掉 1 個怎麼變成 9 隻猴
我們先假設猴子有兩個屬性:編號
和位置
,簡單的栗子,一開始編號和位置是對應的
第一輪選出 2 號:01
2345
6789
第二次選出 5 號:78
0123
456第三次選出 8 號:45
6701
23第四次選出 1 號:12
3456
0第五次選出 6 號:50
1234
第六次選出 0 號:23
401第七次選出 7 號:01
23第八次選出 4 號:12
0第九次選出 9 號:10
最終結果是 3 號:
0
可以看到每次都選 3 選 3 的,雖然出隊的猴的編號不一樣,但是對於新佇列
除去的一定是站在 2 號位置的猴。
這就是我們說的:10 個猴去掉乙個,題目就變成從 9 個猴裡選結果【有點遞迴的意思
要注意一點,實際上程式裡的編號並不是1 ~ n
而是0 ~ n-1
。因為我們在往後推移的時候有可能會超出人數,因此要對人數取餘,而n 的餘數是 0 ~ n-1
因此如果用1 ~ n
來推算會出錯,結果需要+1
,之後看**的時候還會再次說明此事
其次搞清每一輪的結果之間的關係
k是乙個數,每當報數報到 k 就把這個人踢出去,這裡先宣告一下 k ,現在先以 3 為例。
觀察上面的栗子,最開始的序列是
序列 a:01
2345
6789
之後 2 號踢出去之後,因為接下來假裝還是從 0 開始報數,所以 3 號變 0 號
序列 b:78
0123
456
我們會發現,序列 b 中的任何一 個號 i 都滿足乙個式子(bi + 3) % a的長度 = a中對應的數
幾個栗子:
(7+
3)%10
=0(0
+3)%
10=3(
4+3)
%10=7
同理:
第二次選出 5 號:78
0123
456第三次選出 8 號:45
6701
23(7
+3)%
9=1(
5+3)
&9=8
第八次選出 4 號:12
0第九次選出 9 號:10
(0+3
)%3=
0(1+
3)%3
=1
我相信到此為止,大家都了然了,既然公式有了,那還說啥?迴圈就完事了
這裡還要再說一句,因為這個思路從上到下的標號一直在變,公式也是從下往上推算的,因此迴圈的時候也是從求 2 個數的結果
到求 n 個數的結果
。你問 n = 1 的時候怎麼辦?結果不是已經出來了嗎 = =
r 的初始值是 0 ,因為求 1 個猴的話結果直接就是第乙個 - 0 。每次迴圈求的都是答案對應在上一層的編號
推算到最後就得到最後的編號了。如果編號是1 ~ n
的話返回的結果就要+1
。
#include
using
namespace std;
intjo
(int n,
int k)
intmain()
其實我對遞迴的寫法還是挺喜歡的:jo 級函式
int
jojo
(int n,
int k)
我們知道,k 是乙個關鍵數,每當報數報到 k 的時候就處理,那麼這個關鍵數如果改變了怎麼辦呢。只要我們搞清楚每一輪對應的關鍵數是多少就好。
上面說過的第三個栗子:第一輪殺 報 1 的,第二輪殺 報 2 的 . . .這時候我們只需要讓 k 的值變起來就好了
注意:n 個人的時候,k 是 1 ,n 越來越少的時候 k 越來越大,所以這個每一輪對應的 k 值一定要想清楚
#include
using
namespace std;
intjo
(int n,
int k)
intmain()
同樣給出遞迴的方式,各位可以嘗試自己理解一下
int
jojo
(int n,
int k)
國王遊戲我看了好多將約瑟夫環的文章,大都講的不明不白,有的甚至直接給個**。直到看了這篇文章,裡面有把各階段列出來,讓我茅塞頓開。就像我學線段樹那會,有時候對不好理解的**,把每一步改變都列出來對理解和解釋原理都有很大的幫助。請看 -----> 秒懂約瑟夫環
因為猹的小站真的還挺可的,所以那邊更新的也比較勤奮,感謝關注~我會努力的(ง •_•)ง
架構高併發系統簡結
第一部分 建設 提公升效能三步 1 分離應用與資料庫 2 快取 3 應用集群與資料庫集群 需要負載均衡 4 現實問題 分離資料的讀和寫 需要同步工具,分表 5 大型分布式應用架構 第二部分 應急 當已有的應用不能滿足效能需求時 1 重新架構系統 複雜 2 在既有架構下進行擴充套件 即scale ou...
java縱向知識 volatile簡 結
volatile 揮發性 1,保證可見性 2,禁止指令重排序 一定程度保證有序性 3,並不能保證原子性 lock字首指令 記憶體屏障 記憶體柵欄 具體使用條件 1 對變數的寫操作不依賴於當前值 2 該變數沒有包含在具有其他變數的不變式中 某些情況效能優於synchronized 但是不能替代之。使程...
排序 思路簡析(一)
本篇文章總結一下最近學習的排序演算法,提煉出其思想及不同之處。有歸併排序,快速排序,堆排序以及氣泡排序 採用兩兩分解和歸併的策略簡單易行,這樣的歸併排序稱為2 路歸併排序。歸併排序的實現 public static void sort int arr public static void merge...