快手小游戏中有一个游戏叫两点之间的,想要研究个算法能让程序自动计算出解决办法。

基本思路就是使用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秒。以后想到了更好的办法会再更新。有人有更好的想法可以联系我,一起探讨哈哈。

===========================================================================================================================