经典算法详解——状态压缩 DP

状态压缩 DP

到这里,我们知道了 S 到所有 M 的最短距离,也知道了 M 互相之间的最短距离,也知道了 M 到 T 的最短距离,这就是一个经典的状态压缩 DP 的模型了。

复杂度分析

注意事项

  • 由于本题的复杂度较高,使用 Python 等性能较差的语言实现时需要注意效率问题。
  • 本题边界情况较多,比如迷宫没有 M 、M 不可达等。

Python 实现

复制代码
import Queue
​class Solution(object):
    def minimalSteps(self, maze):
        """
        :type maze: List[str]
        :rtype: int
        """
        n = len(maze)
        m = len(maze[0])
        p = []
        #记录所有特殊点
        for i in range(n):
            for j in range(m):
                if maze[i][j] in ['S','T','M','O']:
                    p.append((i,j,maze[i][j]))
        dxs = [0,1,0,-1]
        dys = [1,0,-1,0]
        def bfs(x, y):
            q = Queue.Queue()
            q.put((x,y))
            dis = [[10000 for i in range(m)] for j in range(n)]
            dis[x][y] = 0
            while not q.empty():
                _ = q.get()
                x = _[0]; y = _[1]
                for dx, dy in zip(dxs, dys):
                    nx = x + dx; ny = y + dy
                    if nx < 0 or nx == n or ny < 0 or ny == m: continue
                    if maze[nx][ny] == '#': continue
                    if dis[nx][ny] > dis[x][y] + 1:
                        dis[nx][ny] = dis[x][y] + 1
                        q.put((nx,ny))
            res = []
            for i, j, _ in p:
                res.append(dis[i][j])
            return res
        #计算特殊点之间的最短距离
        tag = {}
        dis = []
        for idx, (i, j, t) in enumerate(p):
            dis.append(bfs(i, j))
            if not t in tag: tag[t] = []
            tag[t].append(idx)
        sidx = tag['S'][0]
        tidx = tag['T'][0]
        
        #特殊处理 M 不存在的情况
        if not 'M' in tag:
            ans = dis[sidx][tidx]
            if ans == 10000:
                ans = -1
            return ans
        
        #计算 S 到所有 M 点之间的最短距离
        Mnum = len(tag['M'])
        Onum = len(tag['O'])
        dp = [[10000 for i in range(Mnum)] for i in range(1<<Mnum)]
        for i in range(Mnum):
            midx = tag['M'][i]
            s = 1 << i 
            for j in range(Onum):
                oidx = tag['O'][j]
                dp[s][i] = min(dp[s][i], dis[sidx][oidx] + dis[oidx][midx])
    # 预处理 M 点之间的最短距离
        Mdis = [[10000 for i in range(Mnum)] for j in range(Mnum)]
        for i in range(Mnum):
            midx1= tag['M'][i]
            for j in range(Mnum):
                midx2 = tag['M'][j]
                for k in range(Onum):
                    oidx = tag['O'][k]
                    Mdis[i][j] = min(Mdis[i][j], dis[midx1][oidx] + dis[oidx][midx2])
                    
    #状态压缩DP
        for s in range(1<<Mnum):
            for j in range(Mnum):
                if s & (1<<j) == 0: continue
                for k in range(Mnum):
                    if s & (1<<k) != 0: continue
                    ns = s | (1<<k)
                    dp[ns][k] = min(dp[ns][k], dp[s][j] + Mdis[j][k])
        
        # 统计结果
        ans = 10000
        fs = (1<<Mnum) - 1
        for j in range(Mnum):
            midx = tag['M'][j]
            ans = min(ans, dp[fs][j] + dis[midx][tidx])
        if ans == 10000: ans = -1
        return ans
相关推荐
阳明山水7 分钟前
TimesFM与Moirai MoE零样本预测解析
人工智能·深度学习·算法·机器学习·架构
铅笔侠_小龙虾20 分钟前
Rust 学习(2)-变量、常量与 shadowing
学习·算法·rust
AI科技星26 分钟前
基于全域数学公理体系的三元极值题最简求解法【乖乖数学】
线性代数·算法·游戏·决策树·机器学习·乖乖数学·全域数学
大鱼>1 小时前
宠物异常行为预警系统:边缘计算与实时检测
人工智能·深度学习·算法·iot·宠物
apcipot_rain2 小时前
某双非机试真题
算法
米尔的可达鸭2 小时前
深入操作系统 Socket 底层:套接字控制块、FD映射、阻塞IO核心完整实现
arm开发·数据结构·websocket·网络协议·算法·架构·安全架构
tachibana23 小时前
hot100 课程表(207)
java·数据结构·算法·leetcode
神仙别闹3 小时前
编写基于C++ Huffman 算法的无损压缩程序和解压程序
java·c++·算法
大鱼>3 小时前
宠物活动轨迹追踪系统:GPS/BDS+UWB+BLE多定位融合方案
人工智能·深度学习·算法·iot·宠物
闲研随记3 小时前
【文献阅读 ICML 2026】RL算法:R2VPO
论文阅读·人工智能·算法·强化学习·icml·rl算法