用DFS求连通块进阶

Posted wanshe-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用DFS求连通块进阶相关的知识,希望对你有一定的参考价值。

UVA-1103(Ancient Messages,World Finals)
点击看图
输入H行W列的字符矩阵(H<=200, W<=50)
每个字符都是16进制数字,将他们转化为二进制后产生的图形中有‘1‘和‘0‘,构成上面的图形。
根据符号内部白色洞的数量来判断。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <vector>
#include <set>
 
using namespace std;
 
const int MAXH = 210;
const int MAXW = 100;
 
int dx[] = {0, 0, -1, 1};
int dy[] = {1, -1, 0, 0};
char* bin[]= {"0000","0001","0010","0011","0100","0101","0110","0111",
            "1000","1001","1010","1011","1100","1101","1110","1111"};
char code[] = "WAKJSD";
 
int W,H;
char pic1[MAXH][MAXW];
char pic[MAXH][MAXW<<2];
int color[MAXH][MAXW<<2];
 
void dfs(int x, int y, int col)
{
    color[x][y] = col;
    for(int i = 0; i < 4; ++i){
        int xx = x + dx[i], yy = y + dy[i];
        if(xx >= 0 && xx < H && yy >= 0 && yy < W
           && pic[x][y] == pic[xx][yy] && !color[xx][yy]){
            dfs(xx,yy,col);
           }
    }
}
 
int main(void)
{
    //freopen("input.txt","r",stdin);
    int cas = 1;
    while(scanf("%d %d", &H, &W), H || W){
 
        memset(pic,0,sizeof(pic));
        memset(color,0,sizeof(color));
 
        for(int i = 0; i < H; ++i)
            scanf("%s",pic1[i]);
        for(int i = 0 ; i < H; ++i){
            for(int j = 0; j < W; ++j){
                if(isdigit(pic1[i][j]))
                    pic1[i][j] -= ‘0‘;
                else
                    pic1[i][j] -= ‘a‘ - 10;
                for(int k = 0; k < 4; ++k)
                    pic[i+1][1 + 4 * j + k] = bin[pic1[i][j]][k] - ‘0‘;
            }
        }
 
        H += 2;
        W = 4 * W + 2;
        int cnt = 0;
        vector<int> cc;
        for(int i = 0; i < H; ++i){
            for(int j = 0; j < W; ++j){
                if(!color[i][j]){
                    dfs(i,j,++cnt);
                    if(pic[i][j] == 1) cc.push_back(cnt);
                }
            }
        }
 
        vector<set<int> > neigh(cnt+1);
        for(int i = 0; i < H; ++i){
            for(int j = 0; j < W; ++j){
               if(pic[i][j]){
                    for(int k = 0; k < 4; ++k){
                        int x = i + dx[k], y = j + dy[k];
                        if(x >= 0 && x < H && y >= 0 && y < W &&
                           pic[x][y] == 0 && color[x][y] != 1)
                            neigh[color[i][j]].insert(color[x][y]);
                    }
                }
            }
        }
 
        vector<char> ans;
        for(int i = 0, sz = cc.size(); i < sz; ++i)
            ans.push_back(code[neigh[cc[i]].size()]);
        sort(ans.begin(),ans.end());
 
        printf("Case %d: ",cas++);
        for(int i = 0, sz = ans.size(); i < sz; ++i)
            printf("%c",ans[i]);
        puts("");
 
    }
    return 0;
}






以上是关于用DFS求连通块进阶的主要内容,如果未能解决你的问题,请参考以下文章

UVA 572 -- Oil Deposits(DFS求连通块+种子填充算法)

油田(Oil Deposits)-用DFS求连通块

用DFS求连通块(种子填充)

UVa572 Oil Deposits (DFS求连通块)

中矿新生赛 H 璐神看岛屿BFS/DFS求联通块/连通块区域在边界则此连通块无效

UVA 572 Oil Deposits(DFS求连通块)