AT_dp_y Grid 2题解
题目描述
有一个高为 H 行、宽为 W 列的网格。我们用 (i,j) 表示从上往下第 i 行、从左往右第 j 列的格子。
在这个网格中,有 N 个格子 (r1,c1), (r2,c2), …, (rN,cN) 是墙,其余的格子都是空格子。保证格子 (1,1) 和 (H,W) 都是空格子。
太郎君从格子 (1,1) 出发,每次只能向右或向下移动到相邻的空格子,他想要到达格子 (H,W)。
请问,从 (1,1) 到 (H,W) 的路径有多少种?请输出答案对 109+7 取模的结果。
输入格式
输入通过标准输入给出,格式如下:
H W N r1 c1 r2 c2 … rN cN
输出格式
输出从 (1,1) 到 (H,W) 的路径数,对 109+7 取模。
显示翻译
题意翻译
输入输出样例
输入 #1复制
3 4 2 2 2 1 4
输出 #1复制
3
输入 #2复制
5 2 2 2 1 4 2
输出 #2复制
0
输入 #3复制
5 5 4 3 1 3 5 1 3 5 3
输出 #3复制
24
输入 #4复制
100000 100000 1 50000 50000
输出 #4复制
123445622
说明/提示
限制条件
- 所有输入均为整数。
- 2≤H,W≤105
- 1≤N≤3000
- 1≤ri≤H
- 1≤ci≤W
- 所有 (ri,ci) 互不相同。
- (1,1) 和 (H,W) 都是空格子。
样例解释 1
路径共有如下图的 3 种。

样例解释 2
也有可能不存在任何路径。
样例解释 4
不要忘记输出答案时要对 109+7 取模。
由 ChatGPT 4.1 翻译
思路
DP即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
struct one{
long long r,c;
}a[3005];
long long n,h,w,f[3005],ff[900005],fn[900005],fc[900005],mod=1e9+7;
bool cmp(one a1,one b1){
if(a1.r!=b1.r) return a1.r<b1.r;
else return a1.c<b1.c;
}
long long qupow(long long a,long long b,long long p){
long long s=1;
while(b){
if(b%2==1) s=(a*s)%p;
a*=a;
b/=2;
a%=p;
}
return s;
}
long long cc(long long x,long long y){
return (ff[x]*fc[y]%mod)*fc[x-y]%mod;
}
int main(){
cin>>h>>w>>n;
for(int i=1;i<=n;i++){
cin>>a[i].r>>a[i].c;
}
a[++n].r=h;
a[n].c=w;
sort(a+1,a+n+1,cmp);
ff[0]=1;
for(int i=1;i<=900000;i++){
ff[i]=(ff[i-1]*i)%mod;
//cout<<i<<" "<<ff[i]<<endl;
}
fn[0]=fn[1]=1;
for(int i=2;i<=900000;i++){
fn[i]=((mod-mod/i)*fn[mod%i]+mod*300000)%mod;
//cout<<i<<" "<<fn[i]<<endl;
}
fc[0]=1;
for(int i=1;i<=900000;i++){
fc[i]=(fc[i-1]*fn[i])%mod;
}
for(int i=1;i<=n;i++){
f[i]=cc(a[i].r+a[i].c-2,a[i].r-1);
//cout<<i<<" "<<f[i]<<endl;
for(int j=1;j<=i-1;j++){
if(a[j].r<=a[i].r&&a[j].c<=a[i].c){
f[i]=(f[i]-f[j]*cc(a[i].r+a[i].c-a[j].r-a[j].c,a[i].r-a[j].r)+mod*mod)%mod;
}
}
}
cout<<(f[n]+mod)%mod<<endl;
return 0;
}

浙公网安备 33010602011771号