十字繡
阿新 • • 發佈:2020-07-08
題目描述
考古學家發現了一塊布,布上做有針線活,叫做“十字繡”,即交替地在布的兩面穿線。
布是一個\(n*m\)的網格,線只能在網格的頂點處才能從布的一面穿到另一面。每一段線都覆蓋一個單位網格的兩條對角線之一,而在繡的過程中,一針中連續的兩段線必須分處布的兩面。並且每一段線只能走一次。
給出布兩面的圖案,問最少需要幾針才能繡出來?一針是指標不離開布的一次繡花過程。
輸入格式
第1行兩個數\(N\)和\(M\)。
接下來\(N\)行每行\(M\)個數描述正面。
再接下來\(N\)行每行\(M\)個數描述反面。
每個格子用.(表示空),\(/\)(表示從右上角連到左下角),\(\$(表示從左上角連到右下角)和\)
輸出格式
一個數,最少要用的針數。
樣例
樣例輸入
4 5
.....
.\...
..\..
.....
.....
....\
.\X..
.....
樣例輸出
4
(為使輸入資料更直觀,樣例為圖片格式,下面是文字格式的樣例)
資料範圍與提示
對於100%的資料,\(1<=n,m<=200\)
code
#include <bits/stdc++.h> using namespace std; const int maxn = 200 + 10; char c[maxn]; int s, n, m; int h[maxn][maxn]; struct node { int t, next; } e[maxn * maxn * 8]; int head[maxn * maxn], f[maxn * maxn], jl[maxn * maxn]; int near[maxn * maxn]; int v[maxn * maxn]; int tot = 0; void add(int x, int y, int z) { f[x] = 1; e[++tot] = (node){ y, head[x] }; head[x] = tot; if (z == 1) jl[x]++; else near[x]++; } void add1(int x, int y, int k) { add(h[x][y + 1], h[x + 1][y], k); add(h[x + 1][y], h[x][y + 1], k); } void add2(int x, int y, int k) { add(h[x][y], h[x + 1][y + 1], k); add(h[x + 1][y + 1], h[x][y], k); } void read(int k) { for (int i = 1; i <= n; i++) { scanf("%s", c + 1); for (int j = 1; j <= m; j++) if (c[j] == 'X') add1(i, j, k), add2(i, j, k); else if (c[j] == '/') add1(i, j, k); else if (c[j] == '\\') add2(i, j, k); } } void dfs(int x) { v[x] = 1; s += abs(jl[x] - near[x]); for (int i = head[x]; i; i = e[i].next) if (!v[e[i].t]) dfs(e[i].t); } int main() { cin >> n >> m; for (int i = 1; i <= n + 1; i++) for (int j = 1; j <= m + 1; j++) h[i][j] = (i - 1) * (m + 1) + j; read(1); read(-1); int ans = 0; for (int i = 1; i <= n + 1; i++) for (int j = 1; j <= m + 1; j++) { int x = h[i][j]; if (!f[x] || v[x]) continue; s = 0; dfs(x); if (s == 0) s = 1; else if (s != 0) s = s / 2; ans += s; } cout << ans; return 0; }