給定 h×w 字符網格,字符為 '/', '\', '.'。'/' 和 '\' 形成閉合多邊形,求所有多邊形內部面積總和。規則:
不能簡單用 4 方向 DFS,因為斜線形成的邊界允許「斜向連通」。例如:
/ . . \
中心區域是內部,但 4 方向無法從一個內部點走到另一個。
從 (x,y) 移動到 (nx,ny) (|dx|=|dy|=1) 時,檢查中間兩個相鄰格子:
#include
#include
using namespace std;
const int MAXN = 128;
char g[MAXN][MAXN];
int vis[MAXN][MAXN];
int h, w, ans;
int dx[4] = {0,0,-1,1}, dy[4] = {1,-1,0,0};
int ddx[4] = {-1,1,1,-1}, ddy[4] = {1,-1,1,-1};
int dfs(int x, int y) {
vis[x][y] = 1;
int area = 1; // 當前點貢獻 1
// 4 直向
for (int k = 0; k < 4; ++k) {
int nx = x + dx[k], ny = y + dy[k];
if (nx < 0 || nx >= h || ny < 0 || ny >= w) return -1; // 觸及邊界 = 外部
if (g[nx][ny] == '.' && vis[nx][ny] == -1) {
int sub = dfs(nx, ny);
if (sub == -1) return -1;
area += sub;
}
}
// 4 斜向
for (int k = 0; k < 4; ++k) {
int nx = x + ddx[k], ny = y + ddy[k];
if (nx < 0 || nx >= h || ny < 0 || ny >= w) return -1;
// 穿越檢測
int minx = min(x, nx), maxx = max(x, nx);
int miny = min(y, ny), maxy = max(y, ny);
if ((minx == nx && miny == ny) || (minx == x && miny == y)) { // 左上→右下
if (g[minx][miny+1] == '/') continue;
}
if ((minx == nx && maxy == ny) || (minx == x && maxy == y)) { // 右上→左下
if (g[minx][miny] == '\\') continue;
}
if (g[nx][ny] == '.' && vis[nx][ny] == -1) {
int sub = dfs(nx, ny);
if (sub == -1) return -1;
area += sub;
}
}
return area;
}
int main() {
scanf("%d%d", &h, &w);
for (int i = 0; i < h; ++i) scanf("%s", g[i]);
memset(vis, -1, sizeof(vis));
ans = 0;
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
if (g[i][j] == '.' && vis[i][j] == -1)
ans = max(ans, dfs(i, j));
// 加上斜線貢獻:每個 '/' 或 '\' 算 0.5
int slash = 0;
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
if (g[i][j] == '/' || g[i][j] == '\\') ++slash;
printf("%.1f\n", ans + slash * 0.5);
return 0;
}