2020-08-30 20:15:35
我分別用窮舉和回溯兩種演算法來實現這個功能,**如下:
#窮舉法:直接用位運算操作整數t的各個二進位制數字,效率更高
def divide_stones_4(a, n):
total = sum(a)
half = total // 2
max_s = 0
lib = tuple(map(lambda x: 1 << x, range(n-1,-1,-1)))#從高到低標記每個二進位制位的1
for t in range(1<
s = 0
for i in range(n):
if t & lib[i] > 0: #t的二進位制數第i位是1,則選擇該堆石子
s += a[i] #累計被選中的石子堆的數量
if max_s < s <= half: #更新最優解
max_s = s
return total - max_s * 2 #返回最小差值
def divide_stones_5(a, n):
total = sum(a)
half = total // 2
max_s = 0
lib = tuple(map(lambda x: 1 << x, range(n-1,-1,-1)))#從高到低標記每個二進位制位的1
def dfs(t, s): #引數:t,正整數,其二進位制數代表當前選擇模式;s,正整數,表示已經選擇的石子數量。
nonlocal max_s
if s > max_s: #更新最優解
max_s = s
for i, bit in enumerate(lib):
if t & bit == 0: #只在第乙個值為1的二進位制位左側設定1,以避免重複
if s+a[i] <= half: #已經超出半數就無需再選擇新的石子堆了
t |= bit #將整數t的第i個二進位制位設定成1
dfs(t, s+a[i])
t &= ~bit #將整數t的第i個二進位制位恢復成0
else:
break
dfs(0, 0)
return total - max_s * 2 #返回最小差值
在窮舉演算法中,無論是用列表b來模擬乙個整數t的n位二進位制數,還是用位運算直接操作整數t的各個二進位制位,都是非常巧妙的方法,每當遇到這種題目,都有令人眼前一亮的感覺。無獨有偶,我有幸遇到了與「石子劃分問題」很相似的一道題目,與大家共同分享。
題目:翻轉棋子遊戲
難度:3星 有趣:3星 有用:3星
分類:窮舉,深搜,廣搜
描述:翻轉棋子遊戲是這樣玩的:
有一張4*4的棋盤,在16個位置上每個位置放著乙個棋子,棋子一面是黑色,另一面是白色,棋子或者白色面朝上,或者黑色面朝上。
遊戲的走法如下:每一步先選擇乙個位置,然後把該位置和上,下,左,右(不越界)相鄰位置上的棋子翻轉(白->黑,黑->白)。
我們用乙個長度為16的字串board儲存棋盤上每顆棋子的顏色狀態,每顆棋子的顏色可以用0、1來表示,0表示白,1表示黑,順序為從左至右,從上至下。
例如,board="1011000111110001",表示的棋盤狀態如下:
當我們選擇第三行,第一列的位置翻轉時,棋盤變化為:
遊戲的目的是用最少的步數把全部棋子變為白色向上或黑色向上。
函式:flip_chess(board)
引數說明:board -- 長度為16的字串,儲存了棋盤上每顆棋子的初始顏色狀態。
返回值:返回最少的翻轉次數,如果無法翻轉成目標狀態,則輸出"impossible"。
樣例1: board="1010000011011001",返回"impossible";
樣例2: board="1001110110011000",返回4。
演算法分析:
初看本題,最容易想到的是窮舉法,用包含16個元素的列表d分別表示每個棋子的翻轉狀態,d[i]=1表示翻轉第i個棋子,d[i]=0表示不翻轉。
可以窮舉從d=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]到d=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],即從都不翻轉到都翻轉。若把列表d對應整數t的16位二進位制數,則相當於窮舉從t=0到t=2^16-1。
我們可以直接用位運算操作整數t的各個二進位制數字,從而生成整數t對應的棋盤翻轉模式,判斷該模式是否有解。若該翻轉模式能獲得更好的解,則更新最優解。
本題的各種演算法也可以用c++語言來實現,兩種語言相比較,我發現由於python語言的自動**記憶體機制和函式式程式設計特徵,以及豐富的內建函式,使得程式設計者無需考慮過多的實現細節,能更關注演算法思想本身,**也更簡潔,更優雅。
python數列翻轉 Python 翻轉列表
python 翻轉列表 定義乙個列表,並將它翻轉。例如,對調第乙個和第三個元素 翻轉前 list 10,11,12,13,14,15 翻轉後 15,14,13,12,11,10 def reverse lst return ele for ele in reversed lst lst 10,11,...
python井字棋 用python井字棋
上篇文章 python 井字棋 文本版 上 電腦端下棋策略是隨機的,有哪些位置可下棋,就隨機選擇乙個位置 實際中是不存這麼傻的對手的,賦予電腦乙個正常的智商還是很有必要的 至少當對手下一步要贏了,我們應該馬上堵住哪個位置 如果電腦自己能贏了,那就應該下能夠贏的位置 如果雙方都贏不了,那就找乙個比較好...
python 翻轉matrix矩陣
題目 給定 matrix 1,2,3 4,5,6 7,8,9 原地旋轉輸入矩陣,使其變為 7,4,1 8,5,2 9,6,3 思路 先沿對角線翻轉,然後沿著中間豎線翻轉。coding utf 8 def print matrix matrix for i in range len matrix ou...