51Nod-1580-铺管道

xiaoxiao2021-02-28  79

ACM模版

描述

题解

这个题的水真深,不得不说这个题的解题思路有些始料未及……

首先通过管道铺设的规则我们可以知道,管道最多只能有两个弯,而且管道口只能再非顶点边缘上,这不免有些让人感觉到复杂,但是也正是这个告诉我们这个题可以转化为求三类折线,贯穿线、折一弯儿端点在临边线、折两弯儿端点在对边线。

于是我们将问题转换为了折点的问题,根据不同折点可以构成的折法,可以求出来我们需要的解。

所以我们可以先求左右方向的情况,再求上下方向的情况,这里将 map 倒置了一下,上下方向的情况按照左右算。

这三类折线中,除了第二类外,其他两类不易重复,所以我们可以将这一类特别考虑,只在第一次左右方向查找时处理一下,由于代码的逻辑原因,这样处理后虽然第二类不重复了,但是第一类少了上下方向的贯穿线,于是在求第一次时,顺便求出纵向贯穿线即可。

具体还是仔细看代码吧,这个代码是我在参考了 rank1 的大神的代码后改写的(实际上也没改嘛子),注释十分详尽,希望可以一目了然……

代码

#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int MAXN = 2005; int n, m; char S[MAXN]; bool A[MAXN][MAXN], B[MAXN][MAXN]; bool D[MAXN][MAXN], U[MAXN][MAXN]; long long ans = 0; void solve(bool T[][MAXN], int n, int m, int flag) { memset(D, 0, sizeof(D)); memset(U, 0, sizeof(U)); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { D[i][j] = D[i - 1][j] | T[i][j]; // 是否可以从 T[i - 1][j] 向下到达 T[i][j] } } for (int i = n; i; i--) { for (int j = 1; j <= m; j++) { U[i][j] = U[i + 1][j] | T[i][j]; // 是否可以从 T[i + 1][j] 向上到达 T[i][j] } } for (int i = 2; i < n; i++) { int tmp = 0; if (!T[i][1] && flag) { tmp = 1; } D[i][1] = U[i][1] = 1; for (int j = 2; j < m; j++) { if (T[i][j]) { tmp = 0; continue; } ans += ((!D[i][j]) + (!U[i][j])) * tmp; // 算 上+[右…右]+下 和 下+[右…右]+上 // 和 上+[右…右]+上 和 下+[右…右]+下 // 以及 从第一列开始 [右…右]+上 和 [右…右]+下 的折线的个数 ans += (!D[i][j] && !U[i][j - 1]) + (!U[i][j] && !D[i][j - 1]); // 算 上+右+上 和 下+右+下 tmp += (!D[i][j - 1]) + (!U[i][j - 1]); // 算 能到达第 i 行的部分数配合下一次循环使用 } if (!T[i][m] && flag) { ans += tmp + (!D[i][m - 1]) + (!U[i][m - 1]); // 算 从前边任何一列开始 下+[右…右] // 和 上+[右…右] 的情况 以及 左右两端 直达的情况 } } if (flag) { for (int j = 2; j < m; j++) { ans += (!D[n][j]); // 算 上下两端 直达的情况 } } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%s", S + 1); for (int j = 1; j <= m; j++) { A[i][j] = S[j] == '#'; } } solve(A, n, m, 1); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { B[j][i] = A[i][j]; } } solve(B, m, n, 0); printf("%lld\n", ans); return 0; }
转载请注明原文地址: https://www.6miu.com/read-66822.html

最新回复(0)