51Nod-1580-铺管道
来源:互联网 发布:开票软件升级 编辑:程序博客网 时间:2024/05/17 04:41
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;}
阅读全文
0 0
- 51Nod-1580-铺管道
- 51nod 1580 铺管道
- 51nod 1580 铺管道(折线问题)
- 51nod 1608 管道安装
- 51Nod 1608 管道安装
- 51Nod
- 51Nod
- 51nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- Axon Framework聚合事件溯源
- 占星术杀人魔法
- Python Tkinter界面应用开发-06 结束
- Docker学习笔记(1)
- 记录昨天20170608
- 51Nod-1580-铺管道
- Spring3核心技术之AOP config配置 proxy-target-class
- java-常用开源库-apache commons
- js调用点击事件
- Bluemix 之云数据库 ClearDB 原理与应用实践
- Spring AOP事务管理(使用切面把事务管理起来)
- raspbain系统连接家庭wifi的配置方法
- 没地方放,先放这吧
- spring @component的作用