围成一圈的排列组合问题_约瑟夫问题
約瑟夫問題由來
據(jù)說著名猶太歷史學家 Josephus有過以下的故事:在羅馬人占領(lǐng)喬塔帕特后,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧愿死也不要被敵人抓到,于是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數(shù),每報數(shù)到第3人該人就必須自殺,然后再由下一個重新報數(shù),直到所有人都自殺身亡為止。然而Josephus 和他的朋友并不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經(jīng)被越過),并殺掉第k個人。接著,再越過k-1個人,并殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續(xù)活著。問題是,給定了人數(shù)總和,一開始要站在什么地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,于是逃過了這場死亡游戲。
17世紀的法國數(shù)學家加斯帕在《數(shù)目的游戲問題》中講了這樣一個故事:15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其余的人才能幸免于難,于是想了一個辦法:30個人圍成一圓圈,從第一個人開始依次報數(shù),每數(shù)到第九個人就將他扔入大海,如此循環(huán)進行,直到僅余15個人為止。問怎樣的?排法,才能使每次投入大海的都是非教徒。
約瑟夫問題算法思想
由于用到四種不同的存儲結(jié)構(gòu),它們的算法思想依次是:
問題分析與算法設(shè)計
約瑟夫問題并不難,但求解的方法很多;題目的變化形式也很多。這里給出一種實現(xiàn)方法。
題目中30個人圍成一圈,因而啟發(fā)我們用一個循環(huán)的鏈來表示,可以使用結(jié)構(gòu)數(shù)組來構(gòu)成一個循環(huán)鏈。結(jié)構(gòu)中有兩個成員,其一為指向下一個人的指針,以構(gòu)成環(huán)形的鏈;其二為該人是否被扔下海的標記,為1表示還在船上。從第一個人開始對還未扔下海的人進行計數(shù),每數(shù)到9時,將結(jié)構(gòu)中的標記改為0,表示該人已被扔下海了。這樣循環(huán)計數(shù)直到有15個人被扔下海為止。
問題示例
設(shè)編號分別為:1,2,...,n的n個人圍坐一圈。約定序號為k(1 <= k < = n)的人從1開始計數(shù),數(shù)到m的那個人出列,他的下一位又從1開始計數(shù),數(shù)到m的那個人又出列,依次類推,直到所有人出列為止;
設(shè)n=8,k=3,m=4時:
出列為:6,2,7,4,3,5,1,8
算法思路:用一個不帶頭結(jié)點的循環(huán)鏈表來處理Josephu問題:先構(gòu)成一個有n個結(jié)點的單循環(huán)鏈表,然后從第k結(jié)點起從1計數(shù),計到m時,對應結(jié)點從鏈表中刪除;然后再從被刪除結(jié)點的下一個結(jié)點起又從1開始計數(shù)....,直到所有結(jié)點都列出時算法結(jié)束。
代碼實現(xiàn):
總結(jié)
以上是生活随笔為你收集整理的围成一圈的排列组合问题_约瑟夫问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从零开始学python人工智能课程_从零
- 下一篇: 编程实现将rdd转换为dataframe