正题
上不了Codeforces,就用洛谷了
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=CF559C
题目大意
H∗WH∗W的棋盘上有一个卒从(1,1)走到(H,W),有些点不能走,求方案总数。
解题思路
首先如果没有障碍走到(i,j)方案数是Ci−1i+j−2Ci+j−2i−1,然后我们可以枚举不可以走的点进行dp。
fifi表示走到第i个不能走的点的方案总数,然后先将所有的点坐标排序,然后动态转移方程:
fi=Cxi−1xi+yi−2−∑j=0i−1fj∗Cxi−xjxi−xj+yi−yjfi=Cxi+yi−2xi−1−∑j=0i−1fj∗Cxi−xj+yi−yjxi−xj
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);
}