题目描述
由数字 00 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 11 构成,围圈时只走上下左右 44 个方向。现要求把闭合圈内的所有空间都填写成 22 .例如: 6 \times 66×6 的方阵( n=6n=6 ),涂色前和涂色后的方阵如下:0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
输入输出格式
输入格式:
每组测试数据第一行一个整数 n(1 \le n \le 30)n(1≤n≤30)接下来 nn 行,由 00 和 11 组成的 n \times nn×n 的方阵。
方阵内只有一个闭合圈,圈内至少有一个 00 。
//感谢黄小U饮品指出本题数据和数据格式不一样. 已修改(输入格式)
输出格式:
已经填好数字 22 的完整方阵。输入输出样例
输入样例#1:
6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
输出样例#1:
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
说明
1 \le n \le 301≤n≤30
乍一看一道求联通块的问题, 好像不是很难的样子.
一开始思路是找到第一个0,然后bfs出所有能达到的零,这个过程中如果触摸到边界,记一个flag,表示是外围,否则内围
一个错误: 没有设置vis数组, 导致死循环.
结果60分.
错在这种数据:
6
0 0 1 1 1 0
1 1 1 0 1 0
1 0 0 0 0 1
1 1 0 1 1 1
0 1 0 1 0 0
0 1 1 1 0 0
题目并没有说外围也是联通的.
so, 做针对性的修改后, 居然40分? wtf? 不增反降?
然后又调出数据, 找到了bug. 原来是遍历那些点需要bfs时, flag没有初始化为1. 是的, flag初始化两次. 其中一次在条件里面.
code show as belew.
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
int row[4] = {-1, 1, 0, 0};
int column[4] = {0, 0, -1, 1};
bool flag = 0; // 刚开始假设是内围
bool vis[33][33] = {}, okya[33][33];
void bfs(vector<vector<int> > &map, int x, int y, int n)
{
queue<pair<int, int> >que;
que.push(make_pair(x, y));
vis[x][y] = okya[x][y] = true;
while (!que.empty()) {
pair<int, int> front = que.front();
que.pop();
map[front.first][front.second] = -1;
for (int i = 0; i < 4; ++i) {
int r = row[i] + front.first, c = column[i] + front.second;
if (r < 0 || r >= n || c < 0 || c >= n) {
flag = 1; // 到边界了, 说明是外围.
continue;
}
if (map[r][c] == 1 || vis[r][c]) continue;
vis[r][c] = okya[r][c] = true;
que.push(make_pair(r, c));
}
}
}
int main()
{
int n;
cin >> n;
vector<vector<int> > map(n, vector<int>(n));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
cin >> map[i][j];
}
}
memset(vis, false, sizeof(vis));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
flag = 1;
if (map[i][j] == 0 && vis[i][j] == false) {
flag = 0;
memset(okya, false, sizeof(okya));
bfs(map, i, j, n);
if (flag == 0) break;
}
}
if (flag == 0) break;
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (okya[i][j]) cout << 2 << ' ';
else if (map[i][j] == -1) cout << 0 << ' ';
else cout << map[i][j] << ' ';
}
cout << endl;
}
}
/*
思路就是找到第一个0,然后bfs出所有能达到的零,这个过程中如果触摸到边界,记一个flag,表示是外围,否则内围
一个错误: 没有设置vis数组.
结果60分.
6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
查看了一下数据发现还有这种情况...所以以后考虑图的联通性还要考虑这样子的.
6
0 0 1 1 1 0
1 1 1 0 1 0
1 0 0 0 0 1
1 1 0 1 1 1
0 1 0 1 0 0
0 1 1 1 0 0
结果是40分, 其他情况错了?
*/