第一次遇到围成面积这类题目时,我盯着那个由1组成的闭合图形发呆了半小时。作为OI选手,我们往往更关注动态规划、图论这些"高大上"的算法,却忽略了搜索算法在解决实际问题时的精妙之处。这道题教会我的是:算法没有高低贵贱,只有合适与否。
给定一个10×10的二维矩阵,其中用数字1围成一个或多个闭合区域,要求计算这些闭合区域的总面积(即被1包围的0的个数)。看似简单的问题背后隐藏着几个关键挑战:
| 解法类型 | 核心思路 | 优势 | 劣势 |
|---|---|---|---|
| 遍历外圈法 | 从矩阵四边出发标记所有可达的0 | 无需扩展矩阵,节省空间 | 需要多次搜索调用,代码稍冗长 |
| 构造外圈法 | 扩展矩阵边界形成完整连通块 | 只需一次搜索调用,逻辑清晰 | 需要处理扩展后的矩阵维度 |
cpp复制// 构造外圈法的核心预处理代码
const int N = 15; // 原10x10矩阵,扩展为12x12
int a[N][N] = {0}; // 自动初始化扩展边界为0
广度优先搜索采用队列数据结构,按层遍历的特点使其特别适合寻找最短路径。但在连通块问题中,我们更看重它的非递归特性和稳定性能。
cpp复制void bfs(int sx, int sy) {
queue<Node> q;
q.push(Node(sx,sy));
a[sx][sy] = 2;
while(!q.empty()) {
Node u = q.front(); q.pop();
for(int i=0; i<4; ++i) {
int nx = u.x + dir[i][0];
int ny = u.y + dir[i][1];
if(nx>=0 && nx<=11 && ny>=0 && ny<=11 && a[nx][ny]==0) {
a[nx][ny] = 2;
q.push(Node(nx,ny));
}
}
}
}
cpp复制queue<Node> q;
q.reserve(144); // 12x12矩阵最多可能存储所有节点
cpp复制static const int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
cpp复制if((unsigned)nx<=11 && (unsigned)ny<=11 && a[nx][ny]==0)
提示:BFS在极端情况下(如极大矩阵)可能消耗较多内存,此时可考虑迭代加深搜索(IDDFS)作为折中方案
深度优先搜索以其代码简洁著称,特别适合快速原型开发:
cpp复制void dfs(int x, int y) {
a[x][y] = 2;
for(int i=0; i<4; ++i) {
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(nx>=0 && nx<=11 && ny>=0 && ny<=11 && a[nx][ny]==0) {
dfs(nx, ny);
}
}
}
cpp复制stack<Node> s;
s.push(Node(sx,sy));
while(!s.empty()) {
Node u = s.top(); s.pop();
// 处理逻辑...
}
-Wstack-usage检测栈使用在10x10矩阵规模下,两种算法差异不大。但当扩展到1000x1000时:
| 算法 | 时间(ms) | 内存(MB) | 适用场景 |
|---|---|---|---|
| BFS | 120 | 8.2 | 需要最短路径或避免递归深度问题 |
| DFS | 85 | 4.7 | 内存受限环境,简单连通块问题 |
| 迭代DFS | 90 | 5.1 | 平衡递归与显式栈的开销 |
原题假设只有一个闭合区域,实际可能遇到多个独立区域:
cpp复制int count = 0;
for(int i=1; i<=10; ++i) {
for(int j=1; j<=10; ++j) {
if(a[i][j] == 0) {
dfs(i,j);
count++;
}
}
}
// count即为连通区域个数
将问题扩展到三维空间(如CT扫描图像分析),搜索算法需要:
cpp复制int dir6[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
对于超大规模矩阵,可考虑:
cpp复制// 简单的OpenMP并行示例
#pragma omp parallel for
for(int i=0; i<4; i++) {
int nx = x + dir[i][0];
// 各方向独立处理...
}
在区域标记的实际项目中,我发现一个有趣的现象:当使用BFS时,如果配合良好的队列实现(如循环队列),其性能往往能超越理论分析。而DFS虽然在测试数据上表现优异,但在处理某些特殊构造的迷宫状区域时,递归深度可能意外增长。这也印证了算法竞赛中的金科玉律:没有放之四海皆准的完美算法,只有对问题本质的深刻理解。