1 条题解

  • 0
    @ 2025-5-25 17:42:46

    核心思路是通过DFS遍历连通区域并分析其几何特征。

    核心逻辑步骤

    连通区域划分
    使用DFS遍历网格中的'1'区域,每个连通区域视为一条"可能的蛇",用vis数组标记已访问的位置。

    蛇的形状特征分析
    对于每个连通区域中的点,根据其邻居数量(4个方向)分类: 邻居数=0:标记为端点(蛇头/尾) 邻居数=1:标记为中间点(蛇身) 邻居数>2:标记为交叉点(说明不是蛇) 用isn字段记录连通区域类型: isn=2:可能是蛇(仅含端点和中间点) isn=3:非蛇(存在交叉点)

    蛇的有效性验证
    isn=2的连通区域,检查端点周围是否满足: 端点相邻的空地是否被蛇身包围 若所有端点周围条件满足,则判定为有效蛇

    关键算法细节

    DFS遍历:递归访问连通区域,记录每个点的邻居数,确定其在"蛇"中的角色(端点/中间点/交叉点)。

    蛇的形状判定
    蛇的定义为"仅有两个端点(邻居数=0)和若干中间点(邻居数=1)",不存在交叉点(邻居数>2)。

    端点验证
    检查端点周围的空地是否被蛇身包围,确保蛇头/尾的合理性。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int n, m;
    int vis[205][205];
    char mp[205][205];
    struct snake{
        int r[3], c[3];
        int nx, isn;
    }sn[20005];
    int dr[] = {0, 0, 1, -1};
    int dc[] = {1, -1, 0, 0};
    void dfs(int r, int c, int u) {
        vis[r][c] = u;
        int t = 0;
        for(int i = 0; i < 4; i++) {
            int nr = r + dr[i];
            int nc = c + dc[i];
            if(nr >= 0 && nr < n && nc >= 0 && nc < m && mp[nr][nc] == '1') {
                t++;
                if(vis[nr][nc] == -1)
                    dfs(nr, nc, u);
            }
        }
        if(t == 0) {
            sn[u].r[0] = r;
            sn[u].c[0] = c;
            sn[u].nx++;
            sn[u].isn = 2;
        }
        if(t == 1) {
            sn[u].r[sn[u].nx] = r;
            sn[u].c[sn[u].nx] = c;
            sn[u].nx++;
            sn[u].isn++;
        }
        if(t > 2)
            sn[u].isn = 3;
    }
    int main() {
        int i, j;
        while(~scanf("%d%d", &n, &m) && (n || m)) {
            memset(vis, -1, sizeof(vis));
            memset(sn, 0, sizeof(sn));
            for(i = 0; i < n; i++) {
                scanf("%s", mp[i]);
            }
            int cnt = 0;
            for(i = 0; i < n; i++) {
                for(j = 0; j < m; j++) {
                    if(mp[i][j] == '1' && vis[i][j] < 0) {
                        dfs(i, j, cnt++);
                    }
                }
            }
            int ans = 0;
            for(i = 0; i < cnt; i++) {
                if(sn[i].isn != 2) continue;
                for(j = 0; j < sn[i].nx; j++) {
                    int t = 0;
                    for(int k = 0; k < 4; k++) {
                        int r = sn[i].r[j] + dr[k];
                        int c = sn[i].c[j] + dc[k];
                        if(r < 0 || r >= n || c < 0 || c >= m || mp[r][c] == '1') {
                            t++;
                            continue;
                        }
                        int sum = 0;
                        for(int l = 0; l < 4; l++) {
                            int nr = r + dr[l];
                            int nc = c + dc[l];
                            if(nr == sn[i].r[j] && nc == sn[i].c[j]) continue;
                            if(nr >= 0 && nr < n && nc >= 0 && nc < m && mp[nr][nc] == '1' )
                                sum = 1;
                        }
                        if(sum)
                            t++;
                    }
                    if(t < 4) break;
                }
                if(j == sn[i].nx) {
                    ans++;
                }
            }
            printf("%d\n", ans);
        }
        return 0;
    }
    
    • 1

    信息

    ID
    2317
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    1
    已通过
    1
    上传者