【TCO2013 Semifinal 2】 OneBlack
来源:互联网 发布:linux 限制某ip访问 编辑:程序博客网 时间:2024/05/03 12:37
Description
一个
你要把一些格子染黑,使得每一条合法路径上恰好有一个黑点。问合法方案数。
Difficulty
MainAlgorithm
对偶图
DP
Complexity
Solution
首先我们把能从
我们观察这些点,他们构成了一个平面图DAG。
考虑一下染色的意义,即一个极小点割。即这个割集中的每一个点都有用而不可删除。
那么,我们把原图转对偶图,在左下角建立S,在右上角建立T,一个合法的方案即为从S到T的一条路径。
DP统计一下就好。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#define Rep(i, x, y) for (int i = x; i <= y; i ++)#define Dwn(i, x, y) for (int i = x; i >= y; i --)#define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex)using namespace std;typedef long long LL;const int N = 1005, M = 45, S = 1001, T = 1002, mod = 1000000007;class OneBlack {public:char a[N][N]; bool vis[M][M], v1[M][M], v2[M][M], ve[N][N], Ch[M][M];LL f[N], num = 1; int in[N], n, m, pos[N], sz, hd, tl, que[N], c[M][M], col, cl, b[N][N];struct Edge { int y, nex; } g[N * N];void Init(int x, int y) {if (x == y || ve[x][y]) return ;g[++ sz] = (Edge) { y, pos[x] }, pos[x] = sz;in[y] ++, ve[x][y] = 1;}void Find(int x, int y) {if (x > n || y > m || vis[x][y] || c[x][y]) return ;c[x][y] = col;Find(x + 1, y), Find(x, y + 1), Find(x + 1, y + 1);}void Dfs(int x, int y) {if (!x || y > m) col = S;if (x > n || !y) col = T;if (col == S || col == T || vis[x][y] || Ch[x][y]) return ;Ch[x][y] = 1;Dfs(x + 1, y), Dfs(x - 1, y), Dfs(x, y - 1), Dfs(x, y + 1);}int countColorings(vector <string> grid) {n = grid.size();m = grid[0].size();Rep(i, 1, n) {Rep(j, 1, m) a[i][j] = grid[i - 1][j - 1];}v1[1][0] = 1, v2[n + 1][m] = 1;Rep(i, 1, n) {Rep(j, 1, m) if (a[i][j] != '#') {v1[i][j] = v1[i - 1][j] | v1[i][j - 1];vis[i][j] = v1[i][j];}}Dwn(i, n, 1) {Dwn(j, m, 1) if (a[i][j] != '#') {v2[i][j] = v2[i + 1][j] | v2[i][j + 1];vis[i][j] &= v2[i][j];}}Rep(i, 1, n) {Rep(j, 1, m) if (a[i][j] != '#' && !vis[i][j]) (num *= 2) %= mod;}Rep(i, 1, n) {Rep(j, 1, m) {if (!c[i][j] && !vis[i][j]) col = (++ cl), Dfs(i, j), Find(i, j);else if (!c[i][j]) b[i][j] = ++ cl;}}Rep(i, 1, n) c[i][0] = T, c[i][m + 1] = S;Rep(i, 1, m) c[0][i] = S, c[n + 1][i] = T;Rep(i, 1, n) {Rep(j, 1, m) {int x = c[i][j];if (!x) {x = b[i][j];if (c[i + 1][j]) Init(x, c[i + 1][j]);if (c[i][j - 1]) Init(x, c[i][j - 1]);if (!c[i + 1][j] && !c[i][j - 1]) Init(x, max(b[i + 1][j - 1], c[i + 1][j - 1]));} else {if (b[i + 1][j]) Init(x, b[i + 1][j]);if (b[i][j - 1]) Init(x, b[i][j - 1]);if (b[i + 1][j - 1]) Init(x, b[i + 1][j - 1]);}if (c[i - 1][j] == S || c[i][j + 1] == S || c[i - 1][j + 1] == S) Init(S, x);}}f[S] = 1, que[hd = tl = 1] = S;while (hd <= tl) {int x = que[hd ++];RepE(i, x) {int y = g[i].y;(f[y] += f[x]) %= mod, in[y] --;if (!in[y]) que[++ tl] = y;}}return int(f[T] * num % mod);}};
0 0
- 【TCO2013 Semifinal 2】 OneBlack
- Topcoder 2016 TCO Algorithm Algo Semifinal 2 Hard
- 【TCO2013 3B】ToastJumping
- 【2012 Semifinal 1】 YetAnotherNim
- Topcoder 2016 TCO Algorithm Algo Semifinal 1 Hard
- 2
- 2
- 2
- 2
- 2
- 2
- 2
- 2
- 2
- 2
- 2
- 2
- 2
- 【RecyclerView】Android 横竖屏切换 超便捷解决方案
- 数据库到底用不用外键
- 不要成为一个懒惰的人
- 手机QQ空间如何显示和修改手机机型型号
- 软件工程师如果没有自学的能力,还是转行吧
- 【TCO2013 Semifinal 2】 OneBlack
- 屏幕适配之Size Classes
- 往linux上部署项目
- HDU 1283 最简单的计算机
- checkbox全选功能javascript实现
- 迷宫走法
- freetype 交叉编译
- 异常
- LTP--linux稳定性测试 linux性能测试 ltp压力测试 ---IBM 的 linux test project