python翻轉棋 Python演算法做翻轉棋子遊戲

2021-10-11 21:55:06 字數 2333 閱讀 4110

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...