题意:给定N*M的矩阵,'*'表示可以通过,'#'表示不能通过,现在要找两条路径从[1,1]到[N,M]去,使得除了起点终点,没有交点。
思路:没有思路,就是裸题。 Lindström–Gessel–Viennot lemma
a到b,c到d,两条路径完全没有交点的方案数=w[a,b]*w[c,d]-w[a,d]*w[b,c];
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) const int maxn=3010; const int Mod=1e9+7; int mp[maxn][maxn],N,M,res; char c[maxn][maxn]; int solve(int sx,int sy,int tx,int ty) { memset(mp,0,sizeof(mp)); mp[sx][sy]=1; rep(i,1,N) rep(j,1,M) { if(c[i][j]=='#') continue; if(c[i-1][j]=='.') (mp[i][j]+=mp[i-1][j])%=Mod; if(c[i][j-1]=='.') (mp[i][j]+=mp[i][j-1])%=Mod; } return mp[tx][ty]; } int main() { scanf("%d%d",&N,&M); rep(i,1,N) scanf("%s",c[i]+1); res=1LL*solve(1,2,N-1,M)*solve(2,1,N,M-1)%Mod-1LL*solve(1,2,N,M-1)*solve(2,1,N-1,M)%Mod; if(res<0) res+=Mod; printf("%d ",res); return 0; }
一道类似的题目:Monotonic Matrix
这里可以重合,但是不能交叉,我们斜着偏移一点即可。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=3010; const int Mod=1e9+7; int C[maxn][maxn],N,M,res; char c[maxn][maxn]; int init() { rep(i,0,maxn-1) C[i][i]=C[i][0]=1; rep(i,1,maxn-1) rep(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod; } int main() { init(); while(~scanf("%d%d",&N,&M)){ int res=1LL*C[N+M][N]*C[N+M][M]%Mod-1LL*C[N+M][N-1]*C[N+M][M-1]%Mod; if(res<0) res+=Mod; printf("%d ",res); } return 0; } /* 1 2 2 2 1000 1000 */