SP20985 UCBINTG - Archipelago[Easy+]
前言
理解题面
这是道初学者基础题,首先了解题目要干什么,才能写出能过的代码,我们读题(关键区已粗体):
\(R\) 行 \(C\) 列的网格表示。字符 X 代表陆地,而 . 代表海洋。
你的任务是计算出五十年后的群岛地图(即海平面上升后留下的样子)。由于未来的陆地可能会更少,输出中不需要显示整个地图,而只需呈现包含所有陆地的最小矩形区。可以保证在所有的测试用例中至少有一个陆地方块能够保留下来(这保证了我们不需要特判无陆地情况)。
更简洁的题面
给定 \(R\) 和 \(C\) 网格,里面有陆地和海洋两种状态。
当陆地的上下左右有三个是被海洋包裹的时他的状态从陆地变为海洋。
地图边界也算作海洋。
最后确定一遍包含陆地的地图部分输出就行。
算法
按照题面描述模拟是 \(O(RC)\) 的,数据范围 \(R,C\) 都在时间复杂度接受的范围,所以可以直接模拟,我们来看题目是如何定义:被淹没的所有四周(东南西北)被海水包围三面或四面的陆地都将被淹没。假定地图边界之外的地方全部被海覆盖。
我们可以理解为当一块陆地上下左右有其中三个及以上是海洋那就是被淹没了。
值得注意的是,被淹没的陆地不会影响旁边陆地的判断,所以我们只需要进行一次操作。
所以我们的思路出来了,遍历一遍整个地图,如果遍历的是陆地,当他上下左右有三个及以上时就变为海洋,最后再次遍历一遍输出包含所有陆地的最小矩形区域就行了。
形式化地,包含所有陆地的最小矩形区域的定义是包含所有陆地的地图,且不存在舍去边缘某一行某一列使得满足此条件。
接下来上代码,码风良好。
时间复杂度:\(O(RC)\)
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_map>
#include <cmath>
#include <climits>
#include <string>
#include <bitset>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int MOD = 998244353;
const int MOD1 = 1e9 + 7;
const double EPS = 1e-8;
void fastOI(){
ios::sync_with_stdio(false);
cin.tie(0);
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
}
int main() {
fastOI();
int R, C;
cin >> R >> C;
vector<string> grid(R);
for (int i = 0; i < R; i++) {
cin >> grid[i];
}
vector<string> future = grid;
// 检查每个陆地格子
for (int r = 0; r < R; r++) {
for (int c = 0; c < C; c++) {
if (grid[r][c] == 'X') {
int sea_count = 0;
// 检查上方向
if (r == 0 || grid[r-1][c] == '.') sea_count++;
// 检查下方向
if (r == R-1 || grid[r+1][c] == '.') sea_count++;
// 检查左方向
if (c == 0 || grid[r][c-1] == '.') sea_count++;
// 检查右方向
if (c == C-1 || grid[r][c+1] == '.') sea_count++;
// 如果三面或四面是海,则被淹没
if (sea_count >= 3) {
future[r][c] = '.';
}
}
}
}
// 找到包含所有剩余陆地的矩形边界
int min_row = R, max_row = -1;
int min_col = C, max_col = -1;
for (int r = 0; r < R; r++) {
for (int c = 0; c < C; c++) {
if (future[r][c] == 'X') {
min_row = min(min_row, r); //所有陆地中的最小行号
max_row = max(max_row, r);//所有陆地中的最大行号
min_col = min(min_col, c);// 所有陆地中的最小列号
max_col = max(max_col, c);//所有陆地中的最大列号
}
}
}
// 输出最小区域
for (int r = min_row; r <= max_row; r++) {
for (int c = min_col; c <= max_col; c++) {
cout << future[r][c];
}
cout << endl;
}
return 0;
}

浙公网安备 33010602011771号