给定一个 \(H*W\)的棋盘,棋盘上只有\(N\) 个格子是黑色的,其他格子都是白色的。

在棋盘左上角有一个卒,每一步可以向右或者向下移动一格,并且不能移动到黑色格子中。求这个卒从左上角移动到右下角,一共有多少种可能的路线

\(1\le H,W\le 10^5,1\le N\le 2000\) 输出对\(10^9+7\)取模

H,W巨大,普通DP不用想,考虑如何用黑格子计数

由组合数学知识可知,从S到T的总路径条数为\(C_{H+W-2}^{H-1}\),只要减去至少经过一个黑格子的路径条数即为答案。

那么如何不重不漏的计数呢?

考虑每条至少经过一个黑格子的路径所包含的第一个黑格子,以4号黑格子(4,5)为例,从S到4号,总路径条数有\(C_{4+5-1-1}^{4-1}\)条,只要排除掉经过3和经过1的路径条数即为从S到4,不经过黑格子的路径数。如何排除?其实我们之前已经算出来了,在算S到4的不经过黑格子路径条数时,已经分别算过了S到3,S到1的不经过黑格子路径条数,只要分别乘上由3到4,由1到4的所有路径数即可。

把所有黑色格子按照行列坐标递增的顺序排序,设\(f[i]\) 为从S到第 \(i\)个格子,途中不经过其他黑色格子的路径数

\[f[i] = C_{x_i-1+y_i-1}^{x_i-1} - \sum_{j=1}^{i-1}f[j]*C_{x_i-x_j+y_i-y_j}^{x_i-x_j},其中x_i\ge x_j,y_i\ge x_j
\]

在求解计数类动态规划时,通常要找一个“基准点",围绕这个基准点构造一个不可划分的”整体",以避免子问题之间的重叠

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
const int N = 2e5+10;
typedef long long ll;
typedef pair<int,int> pii;
#define fi first
#define se second
ll jc[N],inv[N];
int h,w,n;
ll f[2010];
pii a[2010];
ll ksm(ll a,ll b){
ll res = 1;
for(;b;b>>=1){
if(b & 1)res = res * a % mod;
a = a * a % mod;
}
return res;
}
int C(int x,int y){
return jc[x] * inv[y] %mod * inv[x-y] % mod;
}
int main(){
jc[0] = 1;inv[0] = 1;
for(int i=1;i<N;i++)jc[i] = jc[i-1] * i % mod,inv[i] = ksm(jc[i],mod-2);
scanf("%d%d%d",&h,&w,&n);
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].fi,&a[i].se); sort(a+1,a+1+n);
a[n+1].fi = h;a[n+1].se = w; for(int i=1;i<=n+1;i++){
int x = a[i].fi,y = a[i].se;
f[i] = C(x+y-2,x-1);
for(int j=1;j<i;j++){
int xj = a[j].fi;
int yj = a[j].se;
if(xj > x || yj > y)continue;
f[i] = (f[i] - (ll)f[j] * C(x-xj+y-yj,x-xj)%mod + mod)%mod;
}
}
printf("%lld\n",f[n+1]%mod);
return 0;
}

最新文章

  1. MySQL表名和数据库关键字相同解决办法
  2. 如何利用Python生成随机密码
  3. ubuntu12.04静态ip设置问题
  4. poj 1386 Play on Words(有向图欧拉回路)
  5. Windows Azure Virtual Machine (26) 使用高级存储(SSD)和DS系列VM
  6. XMl各种格式转换功能代码
  7. Vmware vsphere 网络架构
  8. Windows Server 2008 R2 辅域控制器如何升级成主域控制器
  9. MySQL管理_数据库常用命令
  10. jQuery coveringBad 效果对比
  11. Oracle Update
  12. Matlab基础
  13. 3D--知识点1
  14. React组件的生命周期各环节运作流程
  15. event.keyCode列表
  16. 通过js修改网页内容
  17. 程序员是这样区分Null和Undefined
  18. 华科机考:a+b
  19. 使用Docker镜像和仓库
  20. 1、Netty 实战入门详解

热门文章

  1. RedHat6.1通过配置yum server安装软件包
  2. 【Flutter】容器类组件之变换
  3. win7安装oracle11g和oracle client和pl/sql
  4. .NET 5 程序高级调试-WinDbg
  5. 音视频入门-20-BMP、PNG、JPG、GIF静态图生成GIF动态图
  6. 跨站脚本漏洞(XSS)基础
  7. 【译】Async/Await(三)——Aysnc/Await模式
  8. VBScript调用winscp,实现sftp操作
  9. xtrabakcup基本用法 安装、全量备份恢复、增量备份恢复
  10. pytest fixtures装饰器的使用