最强大脑《数字迷途》算法及python代码

问题描述:

将n*n数字棋盘空缺位置补齐,使得所有数字按顺序经过所有格子并连成一条曲线,相邻两点之间可通过上下左右和对角线共8种方式连接。

比如下面是试题题面:

 解决算法:

维护一个candidate集合,里面元素表示与当前题面上所存在数字相邻的数字。整体算法使用深度优先搜索,每次在candidate集合中取出一个元素,然后获取可放置位置,遍历有效位置进行递归求解。递归出口:candidate集合为空。

python代码:


class Matrix:
    def __init__(self, grid):
        self.n = len(grid)
        self.grid = grid
        self.visited = [[0 for j in range(self.n)] for i in range(self.n)]
        self.number = {}
        self.candi = set()
    
    def build(self):
        for i in range(self.n):
            for j in range(self.n):
                if self.grid[i][j]!=0:
                    self.number[self.grid[i][j]] = (i, j)
                    self.visited[i][j] = 1
        for num in self.number:
            if num - 1 not in self.number and num!=1:
                self.candi.add(num-1)
            if num + 1 not in self.number and num!=self.n*self.n:
                self.candi.add(num+1)
        self.opts = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, 1), (1, -1)]
    
    def run_model(self):
        self.build()
        f = self.solve()
        for i in range(1, self.n*self.n+1):
            x, y = self.number[i]
            self.grid[x][y] = i
    
    def get_candi_position(self, key):
        res = set()
        x, y = self.number[key]
        for op in self.opts:
            nx ,ny = x+op[0], y+op[1]
            if nx>=0 and nx<self.n and ny>=0 and ny<self.n and self.visited[nx][ny]==0:
                res.add((nx, ny))
        return res
    
    def solve(self):
        if not self.candi:
            return True
        item = list(self.candi)[-1]
        self.candi.remove(item)
        adj_position = set()
        nei1 = set()
        nei2 = set()
        if item + 1 in self.number:
            nei1 = self.get_candi_position(item+1)
        if item - 1 in self.number:
            nei2 = self.get_candi_position(item-1)
        if item + 1 in self.number and item - 1 in self.number:
            adj_position = nei1.intersection(nei2)
        elif item + 1 in self.number:
            adj_position = nei1
        elif item - 1 in self.number:
            adj_position = nei2
        for x, y in adj_position:
            self.number[item] = (x, y)
            self.visited[x][y] = 1
            n1 = False
            n2 = False
            if item + 1 not in self.number and item+1<=self.n*self.n:
                if item+1 not in self.candi:
                    self.candi.add(item+1)
                    n1 = True
            if item - 1 not in self.number and item-1>=1:
                if item-1 not in self.candi:
                    self.candi.add(item-1)
                    n2 = True
            if self.solve():
                return True
            del self.number[item]
            self.visited[x][y] = 0
            if n1:
                self.candi.remove(item+1)
            if n2:
                self.candi.remove(item-1)
        self.candi.add(item)
        return False

    def __str__(self):
        s = []
        for i in range(self.n):
            s_t = ""
            for j in range(self.n):
                s_t += "{:<5}".format(self.grid[i][j])
            s_t += "\n"
            s.append(s_t)
        return "\n".join(s)

grid = [[35,36,0,0,0,49,0],[0,0,39,0,41,0,0],[30,0,0,27,0,0,46],[0,0,1,0,0,23,0],[0,4,0,0,24,0,0],[0,0,0,12,15,0,19],[7,8,0,0,0,0,18]]
m = Matrix(grid)
m.run_model()
print(m)

运行结果:

在最强大脑app填入答案:

 

 成绩排在第9,时间2:19。时间主要消耗在输入输出题面。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值