python解決約瑟夫環問題

2021-10-02 09:21:00 字數 3274 閱讀 4664

問題描述:編號為 1-n 的 n 個士兵圍坐在一起形成乙個圓圈,從編號為 1 的士兵開始依次報數(1,2,3…這樣依次報),數到 m 的 士兵會被殺死出列,之後的士兵再從 1 開始報數。直到最後剩下一士兵,求這個士兵的編號。

有用遞迴函式 f(n,m) 的返回結果是存活士兵的編號,推導出old 與 new 之間的關係為 old = (new + m - 1) % n + 1。即f(n,m)=(f(n - 1, m) + m - 1) % n + 1,號稱可以一行**可以搞定,按著學習的思路。

用python寫出**如下:如果n=6,m=4時:去除的編號為4 2 1 3 6 5;

def

f( n, m):if

(n ==1)

:return n

# print(n-1,m,f(n - 1, m) )

return

(f(n -

1, m)

+ m -1)

% n +

1print

(f(6,4

))

如果去掉#print 的行,一共有5行**;

但發現有兩個問題:

一、推導出最後的數字是對的,但過程中的未顯示出來;

二、如果把f(n-1,m);f(n-2,m)…f(1,m)顯示出來,發現並不是想要的編碼結果;

f(1,4)=1;f(2,4)=1;f(3,4)=2;f(4,4)=2;f(5,4)=1,f(6,4)=5 只有最後的數字是對的;

如何能用比較短的行**來執行出正確的順序並顯示出來呢

寫出**如下:應該有高手來總結出更簡潔的**

n=

6;m=

4;a=

(list

(i for i in

range(1

,n+1))

*3*m);

for j in

range(1

,n):

print

("刪除: "

,a[m-1]

);b=a[m-1]

;a=a[m:];

for i in

range

(len

(a)-1,

-1,-

1):if a[i]

==b:a.pop(i)

print

("剩餘: "

,a[0

])

執行結果如下:

刪除: 4

刪除: 2

刪除: 1

刪除: 3

刪除: 6

剩餘: 5

順序與編號都是一致的,用了6行**;

首先建立乙個大list,讓1到n迴圈3m次(不是口罩了,都賣脫銷了,這裡也沒有;注:2m次會出錯)

然後執行n-1次,從頭數m個數,即為要刪除的數,在此數前全部不要,後面含此數的也遍歷刪除,然後再數m個數。。。直到剩餘乙個數並顯示出來。

不會用for迴圈 和if在一行語句裡判斷,請高手來指導,爭取也能兩行完成。

後記:用第乙個遞推時,執行f(3811,4)時出錯,機器的遞迴深度達到極限了,雖然用

import sys

sys.setrecursionlimit(1000000) #修改遞迴深度的值

但沒有什麼用,第二個程式出錯,

import math

n=10000

;m=4

;a=(

list

(i for i in

range(1

,n+1))

*int((

-1)*math.log(n)

/math.log(

(m-1

)/m)+1

));for j in

range(1

,n):

print

("刪除: "

,a[m-1]

,end='')

;b=a[m-1]

;a=a[m:];

for i in

range

(len

(a)-1,

-1,-

1):if a[i]

==b:a.pop(i)

print

("剩餘: "

,a[0

])

這樣修改了,不出錯了,但**又長了一點。執行時間也長了。但當nimport math

n=10000

;m=4

;a=(

list

(i for i in

range(1

,n+1))

*(3*m if m>n else

int((-

1)*math.log(n)

/math.log(

(m-1

)/m)+1

)));

for j in

range(1

,n):

print

("刪除: "

,a[m-1]

);b=a[m-1]

;a=a[m:];

for i in

range

(len

(a)-1,

-1,-

1):if a[i]

==b:a.pop(i)

print

("剩餘: "

,a[0

])執行正常,能不能再把list只用一次,然後迴圈利用呢,答案是可以的,用擷取再相加的方法,迴圈利用list

n=

12;m=

4;a=

(list

(i for i in

range(1

,n+1))

)for j in

range(1

,n):

d=(m if m<=

len(a)

else

(len

(a)if m%

len(a)==0

else m%

len(a)))

;b=a[

:d-1

];c=a[d-1]

;print

("刪除: "

,c);a=a[d:

];a=a+b

print

("剩餘: "

,a[0

])

其中的條件語句是這樣的:

條件為真的值 if 條件 else 條件為假的值

執行也快,解決,如果能把for 和 print也能寫入一行,就再完美了。

python超簡單解決約瑟夫環問題

明顯的約瑟夫環問題,python實現 如下 a x for x in range 1,31 生成編號 del number 8 該刪除的編號 for i in range 15 print a del number del a del nu程式設計客棧mber del number del numb...

約瑟夫環問題的解決

約瑟夫環問題介紹 已知n個人 以編號1,2,3.n分別表示 圍坐在一張圓桌周圍。從編號為1的人開始報數,數到m的那個人出列 他的下乙個人又從1開始報數,數到m的那個人又出列 依此規律重複下去,直到圓桌周圍的人全部出列。include include include typedef int datat...

c 解決約瑟夫環問題

c 解決約瑟夫環問題 約瑟夫 josephus 問題 m個人圍坐成一圈,從1開始順序編號 遊戲開始,從第乙個人開始由1到n迴圈報數 報到m的人退出圈外問 最後留下的那個人原來的序號 本題可以定義乙個容器 vector 初始化大小 元素個數 為n。容器裡元素的值標識該人是否出局,1在圈內,0出局。值為...