快手小游戏中有一个游戏叫两点之间的,想要研究个算法能让程序自动计算出解决办法。
基本思路就是使用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秒。以后想到了更好的办法会再更新。有人有更好的想法可以联系我,一起探讨哈哈。
===========================================================================================================================