UVA1103 || hdu3839 (Ancient Messages)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3839

题意:给定一个16进制的图,确定相应的字符并按字典序输出。

思路:题意很简单,可以通过找不同字符的洞的数量不同而确定对应的字符,求连通块个数即可。

思路大致可以这样描述:

1. 将16进制的图转换成2进制的图(起点坐标为(1,1)),1表示黑色,0表示白色

2. 先给图的外围加一层0的外壳, 然后从(0,0)开始深搜一遍0的连通块,并将每个点标记成标记成2

3. 经过2操作后剩下的0全是字符内的洞了,然后开始扫描图中为1的点,标记成3,同时,若扫描到的1点旁边有0点,则深搜0的连通块,标记成4

4. 在进行3时,同时计数扫描1这个连通块所能搜到的0的连通块的个数,从而得到对应的字符,加入到ans数组中,如此便得到了答案


代码:

#include
#include
#include
using namespace std;

int h, k, cnt, Rec[205][55*8], map[205][55*8];
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
char rec[205][55], Code[260][5], ans[100000];
const char ANS[7]="WAKJSD";

void input(){for(int i = 1; i <= h; i++) scanf("%s", &rec[i][1]);}

bool legal(int x, int y){return (x>=0&&x<=h&&y>=0&&y<=k);}

bool have_hole(int x, int y){return map[x][y] == 0;}
// 转换成2进制图
void recode(){
    memset(Rec, 0, sizeof(Rec));
    memset(map, 0, sizeof(map));
    for(int i = 1; i <= h; i++){
        for(int j = 1; j <= k; j++){
            for(int m = 0; m < 4; m++){
                Rec[i][j*4-3+m] = Code[rec[i][j]][m]-'0';
                if(Rec[i][j*4-3+m] == 1) map[i][j*4-3+m] = 1;
            }
        }
    }
}
//找连通块
void dfs(int x, int y, int c){
    int t = map[x][y];
    map[x][y] = c;
    for(int i = 0; i < 4; i++){
        int nx = x + dx[i], ny = y + dy[i];
        if(legal(nx, ny) && map[nx][ny] == t){
            dfs(nx, ny, c);
        }
    }
}

void DFS(int x, int y, int c){
    int t = map[x][y];
    map[x][y] = c;
    for(int i = 0; i < 4; i++){
        int nx = x + dx[i], ny = y + dy[i];
        if(legal(nx, ny)){
            if(have_hole(nx, ny)){
                dfs(nx, ny, 4);
                cnt++;
            }
            else if(map[nx][ny] == t){
                DFS(nx, ny, c);
            }
        }

    }
}
//预处理字符
void prepare(){
    strcpy(Code['0'],"0000");
    strcpy(Code['1'],"0001");
    strcpy(Code['2'],"0010");
    strcpy(Code['3'],"0011");
    strcpy(Code['4'],"0100");
    strcpy(Code['5'],"0101");
    strcpy(Code['6'],"0110");
    strcpy(Code['7'],"0111");
    strcpy(Code['8'],"1000");
    strcpy(Code['9'],"1001");
    strcpy(Code['a'],"1010");
    strcpy(Code['b'],"1011");
    strcpy(Code['c'],"1100");
    strcpy(Code['d'],"1101");
    strcpy(Code['e'],"1110");
    strcpy(Code['f'],"1111");
}

int main(){
    prepare();
    int tc = 0;
    while(~scanf("%d %d",&h, &k)){
        if(h == 0 && k == 0) break;
        input();
        recode();
        h += 1;
        k = k*4 + 1;
        dfs(0, 0, 2);
        int CNT = 0;
        for(int i = 0; i <= h;i++){
            for(int j = 0; j <= k; j++){
                if(map[i][j] == 1){
                    cnt = 0;
                    DFS(i, j, 3);
                    ans[CNT++] = ANS[cnt];
                }
            }
        }
        sort(ans, ans+CNT);
        printf("Case %d: ", ++tc);
        for(int i = 0; i < CNT; i++) printf("%c", ans[i]);
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(题解,BFS,DFS)