题目链接: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<cstdio>
#include<cstring>
#include<algorithm>
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;
}