NeFut Logo NeFut
EN 管理员登录

动态规划中的状态空间设计与几何映射

发布于:2026-05-27 09:17 最后更新:2026-06-06 13:04
#C++ #Tutorial

核心逻辑与数学原理

状态空间(State Space)是所有可能状态的集合,是对现实问题阶段性特征的完全离散化抽象。动态规划的实质,就是在状态空间构成的有向无环图(DAG)上寻找最长路或最短路。

若将状态视为高维空间中的格点,转移方程则是这些格点之间的几何向量映射:

  1. 维数与坐标轴:状态数组的维度对应了控制变量的个数。例如,$f[i][j]$ 是二维状态空间,横纵坐标轴分别代表“前 $i$ 个阶段”和“限制条件 $j$”。
  2. DAG 的几何拓扑:任何一个合法的状态转移方程,在几何上都表现为从低维/低标号格点向高维/高标号格点的单向有向边。由于无后效性约束,这些有向边在空间中绝不形成环路。
  3. 空间步长与局部性:转移方程中的标号变化(如 $i-1, j-v$)定义了在状态空间网格中的移动步长。高效的 DP 算法往往具有良好的空间局部性(Spatial Locality),这也是滚动数组能够压缩空间维度的几何依据。

状态设计与算法推导

在 DAG 的几何映射下,我们需要将复杂边界和限制条件转化为坐标轴上的格点控制。以“带障碍物的棋盘路径统计”扩展模型为例:

1. 状态空间设计

设状态 $f[i][j]$ 表示从起点 $(1, 1)$ 沿网格线移动到坐标 $(i, j)$ 的合法路径方案数。若当前坐标 $(i, j)$ 为障碍物,则该格点在状态空间中不合法,值强行归零。

2. 转移方程与几何映射

由于每一步只能向右或向下移动,这意味着目标格点 $(i, j)$ 的前驱格点只能是左侧的 $(i, j-1)$ 和上方的 $(i-1, j)$。这在几何上表现为两条汇聚到 $(i, j)$ 的有向边:

$$f[i][j] = \begin{cases} 0 & \text{if } \text{grid}[i][j] \text{ is obstacle} \\ f[i-1][j] + f[i][j-1] & \text{otherwise} \end{cases}$$

3. 边界与拓扑序


C++ 标准源码(NOIP风格)

以下为基于 DAG 几何映射的二维路径计数源码,包含障碍物处理,严格兼容 NOIP Linux (g++ -O2) 环境。

#include <iostream>
#include <vector>

using namespace std;

const int MAXN = 1005;
const int MOD = 1000000007; // 防爆 int,按题目要求取模

int grid[MAXN][MAXN];
int f[MAXN][MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m;
    if (!(cin >> n >> m)) return 0;

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            cin >> grid[i][j]; // 1 表示空地,0 表示障碍
        }
    }

    // 边界条件初始化
    if (grid[1][1] == 1) {
        f[1][1] = 1;
    }

    // 严格按拓扑序(行列双重循环递增)计算状态空间
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (i == 1 && j == 1) continue; // 跳过起点

            if (grid[i][j] == 0) {
                f[i][j] = 0; // 踩坑点:障碍物处方案数必须强制清零,切勿遗漏
                continue;
            }

            // 状态转移:依赖于几何上方和左方的格点
            f[i][j] = (f[i - 1][j] + f[i][j - 1]) % MOD;
        }
    }

    cout << f[n][m] << "\n";

    return 0;
}

NOIP 实战避坑指南

1. 忽略障碍物状态的显式清零

2. 状态空间拓扑序与循环顺序逆反


经典 NOIP/洛谷 真题

1. 洛谷 P1002 [NOIP2002 普及组] 过河卒

2. 洛谷 P1508 Likecloud-吃糖果

原文链接: local://13.2

[h] 返回首页