题解:P16439 [XJTUPC 2026] 鲜艳 / 方格
看到连通块的题,一眼搜索。
题目大意
给定一个棋盘,判断每个连通块是不是都是矩形。
思路
考虑 dfs。
读入以后,第一步,先循环遍历每一个点。
对于每一个点,如果它已经被访问过了,那就跳到下一个点;否则,在这个点的基础上开始搜索,搜一个连通块,判断是不是矩形。
判断是不是矩形也很简单:搜到每一个点,就把计数器加上 No。
搜索时别忘了标记是否访问过。
代码
#include <bits/stdc++.h>
using namespace std;
char a[505][505];
int dx[5] = {0, 0, 0, -1, 1};
int dy[5] = {0, 1, -1, 0, 0};
int n, m, vis[505][505], cnt, maxx, maxy, minx, miny;
inline int read(){
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-'){
f = -1;
}
c = getchar();
}
while (c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
void dfs(int x, int y, char c){
if (x < 1 || x > n || y < 1 || y > m){//边界
return;
}
vis[x][y] = 1;//是否访问过
cnt++;//计数器
maxx = max(maxx, x);
maxy = max(maxy, y);
minx = min(minx, x);
miny = min(miny, y);//更新最小和最大值
for (int i = 1; i <= 4; i++){//向四个方向搜索
int nx = x + dx[i], ny = y + dy[i];
if (!vis[nx][ny] && c == a[nx][ny]){
dfs(nx, ny, c);
}
}
}
int main(){
int T = read();
while (T--){
n = read(), m = read();
memset(vis, 0, sizeof(vis));//初始化!
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
cin >> a[i][j];
}
}
bool flag = true;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
if (!vis[i][j]){
cnt = 0;
minx = maxx = i;
miny = maxy = j;//初始化!
dfs(i, j, a[i][j]);
if (cnt != (maxx - minx + 1) * (maxy - miny + 1)){
flag = false;
}
}
}
if (!flag){
break;
}
}
cout << (flag ? "Yes" : "No") << endl;
}
return 0;
}
竟然不用开 long long。
完结撒花!