P1162 填涂颜色_bfs

题目描述
由数字 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分, 其他情况错了? 
*/

猜你喜欢

转载自blog.csdn.net/wjh2622075127/article/details/81171774