题目描述
给定一个 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'构成
- 单入口区域要求有且只有一个位于边界的'O'(矩阵边缘)
- 输出要求:
- 唯一最大区域:输出入口坐标和区域大小
- 多个相同大小的最大区域:只输出区域大小
- 没有满足条件的区域:输出"NULL"
关键策略
- 连通区域检测:使用BFS/DFS遍历所有相邻的'O'
- 边界点统计:在遍历时标记位于边界的'O'
- 单入口判断:区域只有一个边界点才是单入口区域
- 结果筛选:找出最大区域,处理多个相同大小的情况
算法流程
1. 遍历矩阵中的每个'O'点
2. 对未访问的'O'进行BFS/DFS:
- 统计区域大小
- 记录所有边界点坐标
3. 判断边界点数量是否为1:
- 是:记录(区域大小, 边界点坐标)
4. 结果处理:
- 没有单入口区域:输出"NULL"
- 唯一最大区域:输出入口坐标和大小
- 多个相同大小区域:输出区域大小
二、完整代码实现
python
from collections import deque
def main():
import sys
data = sys.stdin.read().splitlines()
m, n = map(int, data[0].split())
matrix = []
for i in range(1, 1 + m):
matrix.append(data[i].split())
visited = [[False] * n for _ in range(m)]
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
regions = []# 存储单入口区域信息:(size, entrance_x, entrance_y)
for i in range(m):
for j in range(n):
if matrix[i][j] == 'O' and not visited[i][j]:
queue = deque([(i, j)])
visited[i][j] = True
size = 0
boundary_points = []
while queue:
x, y = queue.popleft()
size += 1
# 检查是否为边界点
if x == 0 or x == m - 1 or y == 0 or y == n - 1:
boundary_points.append((x, y))
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny] and matrix[nx][ny] == 'O':
visited[nx][ny] = True
queue.append((nx, ny))
# 如果是单入口区域
if len(boundary_points) == 1:
x0, y0 = boundary_points[0]
regions.append((size, x0, y0))
# 处理结果
if not regions:
print("NULL")
else:
# 按区域大小降序排序
regions.sort(key=lambda x: x[0], reverse=True)
max_size = regions[0][0]
max_regions = [r for r in regions if r[0] == max_size]
if len(max_regions) > 1:
print(max_size)
else:
size, x, y = max_regions[0]
print(f"{x} {y} {size}")
if __name__ == "__main__":
main()
三、示例解析
示例1:输入
4 4
X X X X
X O O X
X O O X
X O X X
执行过程:
- 检测到区域:包含5个'O'(坐标(1,1),(1,2),(2,1),(2,2),(3,1))
- 边界点:(3,1)(唯一)
- 记录:(size=5, x=3, y=1)
- 输出:
3 1 5
图解:
(0,0) (0,1) (0,2) (0,3)XXXX
(1,0) (1,1) (1,2) (1,3)XOOX
(2,0) (2,1) (2,2) (2,3)XOOX
(3,0) (3,1) (3,2) (3,3)XOXX
边界点↑(红色)
示例2:输入
4 5
X X X X X
O O O O X
X O O O X
X O X X O
执行过程:
- 区域1(左下):7个'O',但有两个边界点(1,0)和(3,1) → 非单入口
- 区域2(右下):1个'O',边界点(3,4)(唯一)
- 记录:(size=1, x=3, y=4)
- 输出:
3 4 1
示例3:输入
5 4
X X X X
X O O O
X O O O
X O O X
X X X X
执行过程:
- 检测到两个分离区域:
- 区域1(第1行):3个'O',边界点(1,3)
- 区域2(第3行):3个'O',边界点(3,3)
- 两个区域大小相同且都是单入口
- 输出:
3
四、总结
关键要点:
- 边界点判断:检查坐标是否在矩阵边缘
- 单入口条件:区域必须有且只有一个边界点
- 结果筛选逻辑:
- 唯一最大区域 → 输出坐标和大小
- 多个相同大小 → 输出大小
- 无满足条件 → 输出"NULL"
注意事项:
- 使用BFS/DFS遍历时注意边界检查
- 访问标记避免重复计算
- 区域大小比较使用降序排序
- 多个相同大小区域只输出大小值
此解法通过系统的区域检测和结果筛选,准确高效地解决了最大单入口空闲区域查找问题,完美符合题目要求。