首页 > 其他分享 >E. Cactus Wall

E. Cactus Wall

时间:2022-11-16 10:24:53浏览次数:70  
标签:dist Wall int second vector Cactus 仙人掌 first

E. Cactus Wall

Monocarp is playing Minecraft and wants to build a wall of cacti. He wants to build it on a field of sand of the size of $n \times m$ cells. Initially, there are cacti in some cells of the field. Note that, in Minecraft, cacti cannot grow on cells adjacent to each other by side — and the initial field meets this restriction. Monocarp can plant new cacti (they must also fulfil the aforementioned condition). He can't chop down any of the cacti that are already growing on the field — he doesn't have an axe, and the cacti are too prickly for his hands.

Monocarp believes that the wall is complete if there is no path from the top row of the field to the bottom row, such that:

  • each two consecutive cells in the path are adjacent by side;
  • no cell belonging to the path contains a cactus.

Your task is to plant the minimum number of cacti to build a wall (or to report that this is impossible).

Input

The first line contains a single integer $t$ $(1 \leq t \leq {10}^{3})$ — number of test cases.

The first line of each test case contains two integers $n$ and $m$ ($2 \leq n,m \leq 2 \cdot {10}^{5}$; $n \times m \leq 4 \cdot {10}^{5}$) — the number of rows and columns, respectively.

Then $n$ rows follow, $i$-th row contains a string $s_i$ of length $m$, where $s_{i,j}$ is '$\text{#}$', if a cactus grows at the intersection of the $i$-th row and the $j$-th column. Otherwise, $s_{i,j}$ is '$\text{.}$'.

The sum of $n \times m$ over all test cases does not exceed $4 \cdot {10}^{5}$.

Output

For each test case, print $\text{NO}$ in the first line if it is impossible to build a cactus wall without breaking the rules. Otherwise, print $\text{YES}$ in the first line, then print $n$ lines of $m$ characters each — the field itself, where the $j$-th character of the $i$-th line is equal to '$\text{#}$', if there is a cactus on the intersection of the $i$-th row and the $j$-th column, otherwise it is '$\text{.}$'. If there are multiple optimal answers, print any of them.

Example

input

4
2 4
.#..
..#.
3 3
#.#
...
.#.
5 5
.....
.....
.....
.....
.....
4 3
#..
.#.
#.#
...

output

YES
.#.#
#.#.
NO
YES
....#
...#.
..#..
.#...
#....
YES
#..
.#.
#.#
...

 

解题思路

  这题关键是要发现如果存在一条从第$1$列斜着走到第$m$列的仙人掌路径,那么就一定不存在从第$1$行走到第$n$行的路径。

  比如样例中的:

  又或者:

  因此问题就变成了是否能够构造出一条从第$1$列斜着走到第$m$列的仙人掌路径,如果不存在则无解,如果存在则给出添加仙人掌数量最少的一条路径。

  由于是斜着走(仙人掌路径),因此一个格子的四个方向是左上、右上、右下、左下。求添加仙人掌数量最小的路径本质就是求最短路,可以用双端队列宽搜,如果走到的下一个格子是仙人掌,那么权值为$0$;否则是空地,权值为$1$,需要注意的是由于空地需要放仙人掌,因此需要保证这个空地的上下左右四个方向都没有仙人掌。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef pair<int, int> PII;
 5 
 6 int n, m;
 7 vector<string> g;
 8 vector<vector<int>> dist;
 9 vector<vector<bool>> vis;
10 vector<vector<PII>> path;
11 
12 bool check(int sx, int sy) {    // 检查空地上下左右四个方向是否存在仙人掌
13     int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
14     for (int i = 0; i < 4; i++) {
15         int x = sx + dx[i], y = sy + dy[i];
16         if (x < 0 || x >= n || y < 0 || y >= m) continue;
17         if (g[x][y] == '#') return false;   // 某个方向存在仙人掌,那么(sx, sy)不可以放仙人掌
18     }
19     return true;
20 }
21 
22 void bfs() {
23     deque<PII> q;
24     dist = vector<vector<int>>(n, vector<int>(m, 0x3f3f3f3f));
25     vis = vector<vector<bool>>(n, vector<bool>(m, 0));
26     path = vector<vector<PII>>(n, vector<PII>(m, {-1, -1}));
27     
28     for (int i = 0; i < n; i++) {   // 第一列的位置入队
29         if (g[i][0] == '#') q.push_front({i, 0}), dist[i][0] = 0;   // 如果是仙人掌则直接入队,权值为0
30         else if (check(i, 0)) q.push_back({i, 0}), dist[i][0] = 1;  // 如果是空地需要保证四周没有仙人掌,权值为1
31     }
32     
33     int dx[4] = {-1, -1, 1, 1}, dy[4] = {-1, 1, 1, -1}; // 斜着的四个方向
34     
35     while (!q.empty()) {
36         PII t = q.front();
37         q.pop_front();
38         if (vis[t.first][t.second]) continue;
39         vis[t.first][t.second] = true;
40         
41         for (int i = 0; i < 4; i++) {
42             int x = t.first + dx[i], y = t.second + dy[i];
43             if (x < 0 || x >= n || y < 0 || y >= m) continue;
44             if (g[x][y] == '#' && dist[x][y] > dist[t.first][t.second]) {   // 下一个格子是仙人掌
45                 dist[x][y] = dist[t.first][t.second];
46                 path[x][y] = {t.first, t.second};
47                 q.push_front({x, y});
48             }
49             else if (g[x][y] == '.' && check(x, y) && dist[x][y] > dist[t.first][t.second] + 1) {   // 下一个格子是空地,一样要保证(x, y)四周没有仙人掌
50                 dist[x][y] = dist[t.first][t.second] + 1;
51                 path[x][y] = {t.first, t.second};
52                 q.push_back({x, y});
53             }
54         }
55     }
56 }
57 
58 void solve() {
59     cin >> n >> m;
60     g = vector<string>(n);
61     for (int i = 0; i < n; i++) {
62         cin >> g[i];
63     }
64     
65     bfs();
66     
67     int x = -1, y = -1; // 找到最短路径最后一列的坐标位置
68     for (int i = 0, minv = 0x3f3f3f3f; i < n; i++) {
69         if (minv > dist[i][m - 1]) {
70             minv = dist[i][m - 1];
71             x = i, y = m - 1;
72         }
73     }
74     
75     if (x == -1) {
76         cout << "NO\n";
77     }
78     else {
79         cout << "YES\n";
80         while (x != -1) {
81             g[x][y] = '#';  // 整条最短路径都标为#
82             PII t = path[x][y];
83             x = t.first, y = t.second;
84         }
85         for (int i = 0; i < n; i++) {
86             cout << g[i] << '\n';
87         }
88     }
89 }
90 
91 int main() {
92     int t;
93     scanf("%d", &t);
94     while (t--) {
95         solve();
96     }
97     
98     return 0;
99 }

 

参考资料

  Educational Codeforces Round 138 D(数学) E(最短路):https://zhuanlan.zhihu.com/p/575721113

标签:dist,Wall,int,second,vector,Cactus,仙人掌,first
From: https://www.cnblogs.com/onlyblues/p/16894950.html

相关文章

  • Wallys/Introduction of DR9074 series network card/qcn9074/qcn9072/qcn9024/indust
    DR9074seriesnetworkcard/qcn9074/qcn9072/qcn9024/industrialM.2card ThisisTinafromWallys,weareaMfgofnetworkingdeviceslikecellularrouters,N......
  • firewalld
    firewalldfirewalld内网的windows3389端口被我映射到了一个公网某端口。最近发现有人不断访问该公网端口,疑似在暴力破解密码。公网服务centos7.6,默认的防火墙工具是fi......
  • WallFilter_简介
    遇到的问题:Caused by: java.sql.SQLException: sql injection violation, dbType mysql, druid-version 1.2.8, part alway true condition not allow : ......
  • 1.firewalld 开放新端口
    1.查看防火墙状态systemctlstatusfirewalld2.查看防火墙开放列表firewall-cmd--zone=public--list-ports3.添加防火墙端口firewall-cmd--add-port=28080/t......
  • Understanding Shared Folders and the Windows Firewall
    https://learn.microsoft.com/zh-cn/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc731402(v=ws.11)......
  • UVA10384 推门游戏 The Wall Pushers(IDA_,A_)
    题目大意给你一个\(4\times6\)的网格图,网格边缘上可能有墙。对于每一个网格有一个权值\(val\),其中\[\begin{aligned}val=&&1(\text{如果这个网格左边缘(西边缘)有墙......
  • Firewalld防火墙
    概述firewalld防火墙是centos7系统默认的防火墙管理工具,取代了之前的iptables防火墙,也是工作在网络层,属于包过滤防火墙。支持IPv4、IPv6防火墙设置以及以太网桥支持服......
  • Linux 系统防火墙 Firewall-cmd 日常操作指南
    1. 管理端口列出dmz级别的被允许的进入端口#firewall-cmd--zone=dmz--list-ports允许tcp端口8080至dmz级别#firewall-cmd--zone=dmz--add-port=8080/tcp允许......
  • Wallys/DR7915-wifi6-MT7915-MT7975-2T2R-support-OpenWRT-802.11AX-supporting-MiniP
    Wallys/DR7915-wifi6-MT7915-MT7975-2T2R-support-OpenWRT-802.11AX-supporting-MiniPCIe-Module//QCA9882/QCA9880 WallyscouldhelpclientsbuildPrototype.Weha......
  • Codeforces 1674 E. Breaking the Wall
    题意给n个数的数列a[n],可以进行任意次操作,每次选取一个位置i,a[i]-=2,a[i-1]-=1,a[i+1]-=1,问最少几次操作可以让任意两个值<=0提示需要进行分类讨论,分成三种情况讨论1.......