- 给定一张(n imes m)的网格图,其中有一些障碍格子。
- 求有多少条从((1,1))到((n,m))的路径,满足除起点和终点外不相交。
- (n,mle3000)
(LGV)引理
一开始智障了,直接无脑套公式,求出((1,1))到((n,m))的方案数(f_{n,m})然后认为答案就是:
[detegin{bmatrix}f_{n,m}&f_{n,m}\f_{n,m}&f_{n,m}end{bmatrix}
]
然后仔细一想不太对劲,众所周知二阶行列式(detegin{bmatrix}a&b\c&dend{bmatrix}=ad-bc),那么上面的式子算出来就是(0)!
是公式出了问题?显然不是。
(LGV)引理要求的不相交是包括起点和终点的,起点和终点相同则肯定相交,因此方案数就是我们算出来的(0)。
所以,我们要让它们开始先各走一步,最后各少走一步,也就是分别从((1,2))走到((n,m-1)),从((2,1))走到((n-1,m))。
于是设(f1_{i,j},f2_{i,j})分别表示从((1,2),(2,1))走到((i,j))的方案数,转移的话如果当前格子是障碍就为(0),否则就是(f_{i,j-1}+f_{i-1,j})。
最终答案就是(detegin{bmatrix}f1_{n-1,m}&f1_{n,m-1}\f2_{n-1,m}&f2_{n,m-1}end{bmatrix}),直接算就好了。
代码:(O(nm))
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 3000
#define X 1000000007
using namespace std;
int n,m,f1[N+5][N+5],f2[N+5][N+5];char s[N+5][N+5];
int main()
{
RI i,j;for(scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%s",s[i]+1);
for(i=1;i<=n;++i) for(j=1;j<=m;++j) s[i][j]^'#'&&//是障碍则方案数为0
(f1[i][j]=i==1&&j==2?1:(f1[i-1][j]+f1[i][j-1])%X,f2[i][j]=i==2&&j==1?1:(f2[i-1][j]+f2[i][j-1])%X);//求出(1,2),(2,1)到每个格子的方案数
return printf("%d
",(1LL*f1[n-1][m]*f2[n][m-1]-1LL*f1[n][m-1]*f2[n-1][m]%X+X)%X),0;//二阶行列式直接计算
}