题解
易得,两条路径一定分别通过\((1,2)\)到\((n-1,m)\)和\((2,1)\)到\((n,m-1)\)的路径。因此可以算出\((1,2)→(n-1,m)\)和\((2,1)→(n,m-1)\)的方案数,将它们相乘,但这样会多余计算在中间有交点的情况。因为\((1,2)→(n,m-1)\)和\((2,1)→(n-1,m)\)的路径一定相交,所以它们方案数之积就等于中间有交点的情况数,减去即可。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3010,mod=1e9+7;
char a[N][N];
int c1[N][N],c2[N][N];
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-') w=-1; ch=getchar();}
while(ch>='0' && ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
signed main()
{
int n=read(),m=read();
for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
if(a[1][2]=='#' || a[2][1]=='#' || a[n][m-1]=='#' || a[n-1][m]=='#') {printf("0"); return 0;}
c1[1][2]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]!='#' && !c1[i][j]) c1[i][j]=(c1[i-1][j]+c1[i][j-1])%mod;
c2[2][1]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]!='#' && !c2[i][j]) c2[i][j]=(c2[i-1][j]+c2[i][j-1])%mod;
printf("%lld",(c1[n-1][m]*c2[n][m-1]%mod-c1[n][m-1]*c2[n-1][m]%mod+mod)%mod);
return 0;
}