快手小游戲中有一個游戲叫兩點之間的,想要研究個算法能讓程序自動計算出解決辦法。

基本思路就是使用dfs路徑搜索,對每一類顏色求解所有的路徑,直到填滿為止。
為了簡化求解過程,我將圖片轉化為了6x6的矩陣,在代碼中直接寫了出來,0代表無顏色,1-5代表不同顏色。
代碼如下:
import copy import datetime #6x6的矩陣 myarr=[[0,0,0,0,3,2], [0,0,0,3,1,0], [1,0,0,0,0,0], [0,0,2,0,0,0], [0,4,5,0,0,5], [0,0,0,0,0,4]] #7x7的矩陣 myarr=[[0, 2, 5, 0, 0, 0, 5], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 3, 2], [0, 0, 0, 0, 0, 0, 0], [3, 4, 1, 0, 0, 1, 4], [0, 0, 6, 0, 0, 0, 0], [6, 0, 0, 0, 0, 0, 0]] #8x8的矩陣 myarr=[[3, 0, 0, 0, 0, 5, 0, 0], [0, 3, 0, 0, 1, 6, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [2, 0, 5, 0, 2, 0, 0, 0], [4, 0, 0, 0, 0, 0, 0, 6], [0, 0, 0, 4, 0, 0, 0, 7], [0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 7]] # myarr=[[1,1,2], # [1,1,0], # [1,1,2]] class dfs_solution(): def __init__(self,arr): self.arr=arr #獲取最大顏色種類 self.maxtype=1 for i in arr: for j in i: if j>self.maxtype: self.maxtype=j self.cols=len(arr[0]) self.rows=len(arr) self.tempSteps=[] self.tempPaths=[] self.solutions=[] #找到當前類的起點和終點 def findStart_end(self,className): point=[] for i in range(len(self.arr)): for j in range(len(self.arr[i])): if self.arr[i][j]==className: point.append([i,j]) return point[0],point[1] #獲取可以走的下一個方塊的坐標 def getNextEle(self, now_row, now_col, className, endPoint): # 順序是上,右,下,左邊 nextArr = [] if now_row >= 1 and (self.arr[now_row - 1][now_col] == 0 or ( self.arr[now_row - 1][now_col] == className and [now_row - 1, now_col] == endPoint)): nextArr.append([now_row - 1, now_col]) if now_col < self.cols - 1 and (self.arr[now_row][now_col + 1] == 0 or ( self.arr[now_row][now_col + 1] == className and [now_row, now_col + 1] == endPoint)): nextArr.append([now_row, now_col + 1]) if now_row < self.rows - 1 and (self.arr[now_row + 1][now_col] == 0 or ( self.arr[now_row + 1][now_col] == className and [now_row + 1, now_col] == endPoint)): nextArr.append([now_row + 1, now_col]) if now_col >= 1 and (self.arr[now_row][now_col - 1] == 0 or ( self.arr[now_row][now_col - 1] == className and [now_row, now_col - 1] == endPoint)): nextArr.append([now_row, now_col - 1]) return nextArr #剪枝:如果結束點沒有路徑可以抵達,就返回False def jianzhi(self,endPoint): nextArr = [] now_row=endPoint[0] now_col=endPoint[1] # temp=[] if now_row >= 1 and (self.arr[now_row - 1][now_col] == 0 or ([now_row - 1, now_col] == self.tempSteps[-1])): # temp.append([now_row - 1, now_col]) return True if now_col < self.cols - 1 and (self.arr[now_row][now_col + 1] == 0 or ( [now_row, now_col + 1] == self.tempSteps[-1])): # temp.append([now_row, now_col + 1]) return True if now_row < self.rows - 1 and (self.arr[now_row + 1][now_col] == 0 or ( [now_row + 1, now_col] == self.tempSteps[-1])): # temp.append([now_row + 1, now_col]) return True if now_col >= 1 and (self.arr[now_row][now_col - 1] == 0 or ([now_row, now_col - 1] == self.tempSteps[-1])): # temp.append([now_row, now_col - 1]) return True # if len(temp)>0: # return True # else: # return False return False #對剩下的所有起點和終點進行判斷剪枝 def jianzhiAll(self,num): result=True for i in range(num,self.maxtype+1): s,e=self.findStart_end(i) result=result and self.jianzhi(s) and self.jianzhi(e) if not result: return False return result #邁步向下一個方塊 def step_to_next(self,num,start,end): nexts=self.getNextEle(self.tempSteps[-1][0],self.tempSteps[-1][1],num,end) for i in nexts: if i == end: self.tempSteps.append(i) self.tempPaths.append(copy.deepcopy(self.tempSteps)) self.tempSteps.pop() continue self.arr[i[0]][i[1]]=num self.tempSteps.append(i) if self.jianzhi(end) and self.jianzhiAll(num+1): self.step_to_next(num,start,end) else: pass self.arr[i[0]][i[1]] = 0 self.tempSteps.pop() #得到元素之間所有的路徑走法 def get_paths(self,num): self.tempPaths=[] start,end=self.findStart_end(num) self.tempSteps=[start] self.step_to_next(num,start,end) return copy.deepcopy(self.tempPaths) #填充 def fillArr(self,paths,num): for i in paths[1:len(paths)-1]: self.arr[i[0]][i[1]]=num #去填充 def unfillArr(self,paths,num): for i in paths[1:len(paths)-1]: self.arr[i[0]][i[1]]=0 #判斷是否完成 def isFinished(self): for i in self.arr: if 0 in i: return False return True #dfs求解所有種類的解 def dfs(self,num): if self.isFinished() and num>self.maxtype: return True if num>self.maxtype: return False start,end = self.findStart_end(num) paths=self.get_paths(num) # print(len(paths)) if len(paths)==0: return False for i in paths: self.fillArr(i,num) self.solutions.append(copy.deepcopy(i)) # if i ==[[0, 1], [0, 0], [1, 0], [2, 0], [2, 1], [1, 1]]: # print(self.arr) if self.dfs(num+1): return self.arr else: # self.solutions.pop(copy.deepcopy(i)) self.unfillArr(i,num) starttime = datetime.datetime.now() s=dfs_solution(myarr) s.dfs(1) for i in s.arr: print(i) endtime = datetime.datetime.now() print((endtime - starttime).seconds) # print(len(s.solutions))
雖然加了剪枝,但是效果還不是非常好。在計算6階以下的時候速度很快,7階的時候需要8秒,8階的時候要569秒。以后想到了更好的辦法會再更新。有人有更好的想法可以聯系我,一起探討哈哈。
===========================================================================================================================
