思路:从给定坐标开始bfs,将所有联通点标记,然后把每个联通点的四个方向都判断一下,如果这个方向相邻的是一个非联通点说明需要把这条边实在最外围,即周长的一部分。


AC代码

#include <stdio.h>
#include<string.h>
#include <queue>
using namespace std;
const int maxn = 100+5;

int a[maxn][maxn];
bool con[maxn][maxn], vis[maxn][maxn];
int n, m;

struct Pos{
    int x, y;
    Pos(int x, int y):x(x), y(y){
    }
};

const int dx[] = {0,0,1,-1};
const int dy[] = {1,-1,0,0};

bool isVis(int x, int y) {
    if(x < 0 || y < 0 || x >= n || y >= m) return false;
    return true;
}

void bfs(int x, int y) {
    memset(vis, 0, sizeof(vis));
    memset(con, 0, sizeof(con));
    queue<Pos>Q;
    vis[x][y] = true;
    con[x][y] = true;
    Q.push(Pos(x, y));
    while(!Q.empty()) {
        Pos p = Q.front();
        Q.pop();
        int x = p.x, y = p.y;
        for(int i = 0; i < 4; i++) {
            int px = x + dx[i];
            int py = y + dy[i];
            if(!isVis(px, py) || vis[px][py]) continue;
            if(a[x][y] != a[px][py]) {
                vis[px][py] = 1;
                continue;
            }
            vis[px][py] = 1;
            con[px][py] = 1;
            Q.push(Pos(px, py));
        }
    }
}

int solve(int x, int y) {
    bfs(x, y);
    int ans = 0;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            if(con[i][j]) {
                for(int k = 0; k < 4; k++) {
                    int x = i + dx[k];
                    int y = j + dy[k];
                    if(!isVis(x, y) || !con[x][y]) {
                        ans++;
                    }
                }
            }
        }
    }
    return ans;
}

int main() {
    int x, y;
    scanf("%d%d%d%d", &n, &m, &x, &y);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            scanf("%d", &a[i][j]);
        }
    }
    printf("%d\n", solve(x, y));
    return 0;
}

如有不当之处欢迎指出!

05-08 08:04