带障碍的网格图dp
给定一个 \(n \times m\) 的网格图,其中若干位置设置了障碍,每一次只能向下或向右移动一格,求从左下角到右下角的不同路径方案数。
这个问题非常经典,用朴素的 \(O(nm)\) dp 是最常见的一种解决方式。然而当 \(n \times m\) 特别大时就不能这样做了。这里记录一种利用容斥 \(O(障碍数^{2})\) 的做法,在障碍数特别少时非常适用。
做法的核心利用了计数映射。对于任意一条从起点到终点的路径,可能不经过障碍,也可能会经过若干个障碍,而我们只需要统计前者的数量。那么对于任意一条经过了障碍的路径,我们只在它经过的第一个障碍处统计该路径的贡献。
于是,令 \(f_{i}\):对于第 \(i\) 个障碍 \((x, y)\),从 \((1, 1)\) 到 \((x, y)\),除了 \((x, y)\) 以外不经过其他任何障碍,不同路径方案数。
结合容斥原理,我们很容易发现:
\[f_{i} = C_{x + y - 2}^{x-1} - (\sum_{p_{j}=(x',y')<(x,y)} f_{j} * C_{x-x'+y-y'}^{x-x'})
\]
因为除了 \((x, y)\) 外,对于终点为 \((x, y)\) 的路径,可能经过的第一个障碍只会是在以 \((1, 1)\) 为左上角、\((x, y)\) 为右下角的矩形范围内的障碍,而 “第一次经过的障碍” 不同也直接导致了路径两两不同,因此可以直接容斥掉。
对于 \(f_{i}\) 条从 \((1, 1)\) 到 \(p_{i} = (x, y)\) 的所有路径,由于保证了 \(p_{i}\) 处的障碍第一次经过,因此后面走到 \((n, m)\) 的过程就无所谓了,直接用组合数求解即可。
答案即为:
\[C_{n+m-2}^{n-1} - (\sum_{p_{k}=(x,y)} f_{k}*C_{n-x+m-y}^{n-x})
\]
下面是例题:

浙公网安备 33010602011771号