問題描述:編號為 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):
("刪除: "
,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)
("剩餘: "
,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出局。值為...