正题
上不了Codeforces,就用洛谷了
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=CF559C
题目大意
H∗W H ∗ W 的棋盘上有一个卒从(1,1)走到(H,W),有些点不能走,求方案总数。
解题思路
首先如果没有障碍走到(i,j)方案数是
Ci−1i+j−2
C
i
+
j
−
2
i
−
1
,然后我们可以枚举不可以走的点进行dp。
fi
f
i
表示走到第i个不能走的点的方案总数,然后先将所有的点坐标排序,然后动态转移方程:
fi=Cxi−1xi+yi−2−∑j=0i−1fj∗Cxi−xjxi−xj+yi−yj
f
i
=
C
x
i
+
y
i
−
2
x
i
−
1
−
∑
j
=
0
i
−
1
f
j
∗
C
x
i
−
x
j
+
y
i
−
y
j
x
i
−
x
j
code
#include<cstdio>
#include<algorithm>
#define N 2001
using namespace std;
const int BPM=1000000007;
struct node{
int x,y;
}a[N];
int h,w,n,f[N];
long long jc[200010],jcinv[200010];
long long power(long long a,int b)//快速幂
{
long long c=1;
while(b)
{
if(b&1) c=c*a%BPM;
a=a*a%BPM;
b>>=1;
}
return c;
}
int C(int n,int m)//求组合数
{
return jc[n]*jcinv[m]%BPM*jcinv[n-m]%BPM;
}
bool cmp(node x,node y)//坐标排序
{
return x.x==y.x?x.y<y.y:x.x<y.x;
}
int main()
{
jc[0]=1;jcinv[0]=1;
for(int i=1;i<=200000;i++)
{
jc[i]=jc[i-1]*i%BPM;
jcinv[i]=power(jc[i],BPM-2);
}//预处理求组合数
scanf("%d%d%d",&h,&w,&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+1+n,cmp);
a[n+1].x=h;a[n+1].y=w;//结束
for(int i=1;i<=n+1;i++){
f[i]=C(a[i].x+a[i].y-2,a[i].x-1);
for(int j=1;j<i;j++)
{
if(a[j].x>a[i].x||a[j].y>a[i].y)
continue;//不在左上角
f[i]=(f[i]-(long long)f[j]*C(a[i].x+a[i].y-a[j].x-a[j].y,
a[i].x-a[j].x))%BPM;//动态转移
}
}
printf("%d",(f[n+1]+BPM)%BPM);
}