【TCO2013 Semifinal 2】 OneBlack
生活随笔
收集整理的這篇文章主要介紹了
【TCO2013 Semifinal 2】 OneBlack
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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);} };總結
以上是生活随笔為你收集整理的【TCO2013 Semifinal 2】 OneBlack的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java西语_使用Java 8 Date
- 下一篇: 怎样用万用表检测贴片三极管