CF 348 D. Turtles

D. Turtles

链接

题意:

  给定一个N*M的棋盘,有些格子不能走,问有多少种从(1,1)到(N,M)的两条不相交路径。

分析:

  lGV定理

  定理:点集A={a1,a2,…an}A={a1,a2,…an}到B={b1,b2,…bn}B={b1,b2,…bn}的不相交路径条数等于下面矩阵的行列式。

  $$\begin{bmatrix} e(a_1, b_1) & e(a_1, b_2) & \dots & e(a_1, b_n) \\ e(a_2, b_1) & e(a_2, b_2) & \dots & e(a_2, b_n) \\ \dots & \dots & \dots & \dots \\ e(a_n, b_1) & e(a_n, b_2) & \dots & e(a_n, b_n) \\ \end{bmatrix}$$

  e(a,b)为从点a到点b的路径条数,本质是容斥。

  这道题目中,任意一条合法的路径都是从(1,2)->(n-1,m)和(2,1)->(n,m-1)的,所以$A=\{(1,2),(2,1)\}$,$B=\{(n-1,m),(n,m-1)\}$。  

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 3005, mod = 1e9 + 7;
int f[N][N];
char s[N][N];

int Calc(int a,int b,int c,int d) {
    memset(f, 0, sizeof(f));
    for (int i = a; i <= c; ++i) 
        for (int j = b; j <= d; ++j) 
            if (s[i][j] == '.') {
                if (i == a && j == b) f[i][j] = 1;
                else f[i][j] = (f[i - 1][j]  + f[i][j - 1]) % mod;
            }
    return f[c][d];
}
int main() {
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i) scanf("%s", s[i] + 1); 
    LL t1 = Calc(1, 2, n - 1, m), t2 = Calc(2, 1, n, m - 1);
    LL t3 = Calc(1, 2, n, m - 1), t4 = Calc(2, 1, n - 1, m);
    cout << (t1 * t2 % mod - t3 * t4 % mod + mod) % mod;
    return 0;
}

 

posted @ 2019-01-29 16:20  MJT12044  阅读(219)  评论(0编辑  收藏  举报