Codeforces Round #202 (Div. 1) D. Turtles

来源:互联网 发布:2015年进出口数据 编辑:程序博客网 时间:2024/05/11 17:14

深受数学竞赛影响,一开始在想折线计数方法,想用容斥原理来搞定有不能取的点的情况,事实说明我是个傻吊。。。3000*3000,有可能全是不能取的点,这么多点用个毛线容斥。。。刷题少了!!!!肯定DP啊,而且方程是十分简单,但是题目中有个限制是两条路径不能相交,这就需要大神的指引了!题解给出的是rng_58给的高贵冷艳的Lindström–Gessel–Viennot 引理,见链接:http://en.wikipedia.org/wiki/Lindstr%C3%B6m%E2%80%93Gessel%E2%80%93Viennot_lemma。

表示没大看懂,更不要说证明了,但是会用就行,直接把结论拿过来,两个点集,A, B, 从A中一个点到B的所有路径中不相交的路径对数等于以下这个矩阵的行列式:

 M = \begin{pmatrix} e(a_1,b_1) & e(a_1,b_2) & \cdots & e(a_1,b_n) \\ e(a_2,b_1) & e(a_2,b_2) & \cdots & e(a_2,b_n) \\ \vdots & \vdots & \ddots & \vdots \\ e(a_n,b_1) & e(a_n,b_2) & \cdots & e(a_n,b_n) \end{pmatrix} .

其中e(a, b)表示a 到 b的路径条数。所以答案是

我们取初始集合为A((0, 1), (1, 0)) B((n - 1), m - 2) (n - 2, m - 1)即可。

代码:

dp部分写成函数会减少代码量。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define N 3005#define Mod 1000000007 using namespace std;long long dp[2][N][N], m, n;char s[N][N];void go (int k, int x, int y){int i, j;if (s[x][y] == '.') dp[k][x][y] = 1;for (i = x; i < n; ++i)for (j = y; j < m; ++j){if (s[i][j] == '.' && (i != x || j != y))dp[k][i][j] = ((i >= 1 ? dp[k][i - 1][j] : 0) + (j >= 1 ? dp[k][i][j - 1] : 0)) % Mod;}} int main(){int i, j, k;long long re;cin >> n >> m;for (i = 0; i < n; ++i) scanf("%s", s[i]);go(0, 0, 1), go(1, 1, 0);re = abs(dp[1][n -1][m - 2] * dp[0][n - 2][m - 1] % Mod - dp[1][n - 2][m - 1] * dp[0][n - 1][m - 2] % Mod + Mod) % Mod;printf("%I64d\n", re);return 0; }


原创粉丝点击