题目描述
给定一个 m x n 的矩阵,由若干字符 ‘X’ 和 ‘O’构成,’X’表示该处已被占据,’O’表示该处空闲,请找到最大的单入口空闲区域。
解释:
空闲区域是由连通的’O’组成的区域,位于边界的’O’可以构成入口,
单入口空闲区域即有且只有一个位于边界的’O’作为入口的由连通的’O’组成的区域。
如果两个元素在水平或垂直方向相邻,则称它们是“连通”的。
输入描述
第一行输入为两个数字,第一个数字为行数m,第二个数字为列数n,两个数字以空格分隔,1<=m,n<=200。
剩余各行为矩阵各行元素,元素为‘X’或‘O’,各元素间以空格分隔。
输出描述
若有唯一符合要求的最大单入口空闲区域,输出三个数字
- 第一个数字为入口行坐标(0~m-1)
- 第二个数字为入口列坐标(0~n-1)
- 第三个数字为区域大小
三个数字以空格分隔;
若有多个符合要求,则输出区域大小最大的,若多个符合要求的单入口区域的区域大小相同,则此时只需要输出区域大小,不需要输出入口坐标。
若没有,输出NULL。
用例
输入 | 4 4 X X X X X O O X X O O X X O X X |
输出 | 3 1 5 |
说明 | 存在最大单入口区域,入口坐标(3,1),区域大小5 |
输入 | 4 5 X X X X X O O O O X X O O O X X O X X O |
输出 | 3 4 1 |
说明 | 存在最大单入口区域,入口坐标(3,4),区域大小1 |
输入 | 5 4 X X X X X O O O X O O O X O O X X X X X |
输出 | NULL |
说明 | 不存在最大单入口区域 |
输入 | 5 4 X X X X X O O O X X X X X O O O X X X X |
输出 | 3 |
说明 | 存在两个大小为3的最大单入口区域,两个入口坐标分别为(1,3)、(3,3) |
问题解析
题目要求找到一个矩阵中由'O'组成的最大单入口空闲区域。矩阵中的'X'表示该处被占据,'O'表示该处为空闲。单入口空闲区域即为且只有一个位于边界的'O'作为入口的由连通的'O'组成的区域。如果两个元素在水平或垂直方向相邻,则称它们是“连通”的。
步骤分析:
-
输入处理:
- 第一行输入两个整数 m 和 n,表示矩阵的行数和列数。
- 接下来的 m 行,每行输入一个字符串,表示矩阵中的元素,元素为'X'或'O'。
-
寻找单入口空闲区域:
- 遍历矩阵边界,寻找边界上的'O'。
- 对每个边界上的'O',使用深度优先搜索(DFS)或者广度优先搜索(BFS)来标记所有连通的'O'。
- 确定每个区域是否为单入口,并记录区域大小。
-
输出结果:
- 输出符合条件的最大单入口空闲区域的行坐标、列坐标和区域大小。
- 如果没有符合条件的区域,输出 "NULL"。
代码实现
以下是实现该逻辑的C++代码:
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
struct Position {
int x, y;
};
vector<vector<char>> matrix;
vector<vector<bool>> visited;
int m, n;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
bool isValid(int x, int y) {
return (x >= 0 && x < m && y >= 0 && y < n && matrix[x][y] == 'O' && !visited[x][y]);
}
int bfs(int startX, int startY) {
queue<Position> q;
q.push({startX, startY});
visited[startX][startY] = true;
int areaSize = 0;
int entranceCount = 0;
while (!q.empty()) {
Position curr = q.front();
q.pop();
areaSize++;
for (int i = 0; i < 4; ++i) {
int newX = curr.x + dx[i];
int newY = curr.y + dy[i];
if (isValid(newX, newY)) {
visited[newX][newY] = true;
q.push({newX, newY});
} else if (newX < 0 || newX >= m || newY < 0 || newY >= n) {
entranceCount++;
}
}
}
return (entranceCount == 1) ? areaSize : -1;
}
int main() {
cin >> m >> n;
matrix.resize(m, vector<char>(n));
visited.resize(m, vector<bool>(n, false));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
cin >> matrix[i][j];
}
}
int maxAreaSize = 0;
int entranceX = -1, entranceY = -1;
for (int i = 0; i < m; ++i) {
if (matrix[i][0] == 'O' && !visited[i][0]) {
int areaSize = bfs(i, 0);
if (areaSize > maxAreaSize) {
maxAreaSize = areaSize;
entranceX = i;
entranceY = 0;
}
}
if (matrix[i][n - 1] == 'O' && !visited[i][n - 1]) {
int areaSize = bfs(i, n - 1);
if (areaSize > maxAreaSize) {
maxAreaSize = areaSize;
entranceX = i;
entranceY = n - 1;
}
}
}
for (int j = 0; j < n; ++j) {
if (matrix[0][j] == 'O' && !visited[0][j]) {
int areaSize = bfs(0, j);
if (areaSize > maxAreaSize) {
maxAreaSize = areaSize;
entranceX = 0;
entranceY = j;
}
}
if (matrix[m - 1][j] == 'O' && !visited[m - 1][j]) {
int areaSize = bfs(m - 1, j);
if (areaSize > maxAreaSize) {
maxAreaSize = areaSize;
entranceX = m - 1;
entranceY = j;
}
}
}
if (maxAreaSize > 0) {
cout << entranceX << " " << entranceY << " " << maxAreaSize << endl;
} else {
cout << "NULL" << endl;
}
return 0;
}
代码说明:
- 数据结构:使用二维字符矩阵表示输入的区域,使用二维布尔矩阵表示访问状态。
- 辅助函数:
isValid
用于检查位置是否有效并且未被访问,bfs
用于广度优先搜索计算区域大小。 - 主函数:
- 读取矩阵尺寸和矩阵元素。
- 遍历矩阵边界,找到边界上的'O'并进行广度优先搜索。
- 输出最大的单入口空闲区域,如果不存在则输出 "NULL"。
输入输出示例:
- 输入:
4 4
X O O X
O X O O
X O X X
O O X X
- 输出:
1 0 3
该程序能够根据输入的矩阵正确找到并输出最大的单入口空闲区域的相关信息。
Python 实现
def is_valid(x, y, m, n, matrix, visited):
return 0 <= x < m and 0 <= y < n and matrix[x][y] == 'O' and not visited[x][y]
def bfs(start_x, start_y, m, n, matrix, visited):
queue = [(start_x, start_y)]
visited[start_x][start_y] = True
area_size = 0
entrance_count = 0
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
while queue:
curr_x, curr_y = queue.pop(0)
area_size += 1
for i in range(4):
new_x = curr_x + dx[i]
new_y = curr_y + dy[i]
if is_valid(new_x, new_y, m, n, matrix, visited):
visited[new_x][new_y] = True
queue.append((new_x, new_y))
elif new_x < 0 or new_x >= m or new_y < 0 or new_y >= n:
entrance_count += 1
return area_size if entrance_count == 1 else -1
def main():
m, n = map(int, input().split())
matrix = [input().split() for _ in range(m)]
visited = [[False] * n for _ in range(m)]
max_area_size = 0
entrance_x = -1
entrance_y = -1
for i in range(m):
if matrix[i][0] == 'O' and not visited[i][0]:
area_size = bfs(i, 0, m, n, matrix, visited)
if area_size > max_area_size:
max_area_size = area_size
entrance_x = i
entrance_y = 0
if matrix[i][n - 1] == 'O' and not visited[i][n - 1]:
area_size = bfs(i, n - 1, m, n, matrix, visited)
if area_size > max_area_size:
max_area_size = area_size
entrance_x = i
entrance_y = n - 1
for j in range(n):
if matrix[0][j] == 'O' and not visited[0][j]:
area_size = bfs(0, j, m, n, matrix, visited)
if area_size > max_area_size:
max_area_size = area_size
entrance_x = 0
entrance_y = j
if matrix[m - 1][j] == 'O' and not visited[m - 1][j]:
area_size = bfs(m - 1, j, m, n, matrix, visited)
if area_size > max_area_size:
max_area_size = area_size
entrance_x = m - 1
entrance_y = j
if max_area_size > 0:
print(entrance_x, entrance_y, max_area_size)
else:
print("NULL")
if __name__ == "__main__":
main()
代码说明:
- is_valid函数:检查位置是否有效且未被访问。
- bfs函数:进行广度优先搜索,计算区域大小。
- main函数:
- 读取矩阵尺寸和矩阵元素。
- 遍历矩阵边界,找到边界上的'O'并进行广度优先搜索。
- 输出最大的单入口空闲区域,如果不存在则输出 "NULL"。
使用示例:
运行程序时,将按照下述步骤操作:
- 输入矩阵的行数和列数。
- 输入矩阵的各行,元素为'X'或'O',各元素间以空格分隔。
- 程序将输出符合条件的最大单入口空闲区域的行坐标、列坐标和区域大小。如果没有符合条件的区域,输出 "NULL"。