[uva]AncientMessages象形文字识别 (dfs求连通块)
非常有趣的一道题目,大意是给你六种符号的16进制文本,让你转化成二进制并识别出来
代码实现上参考了//http://blog.csdn.net/u012139398/article/details/39533409
#include<cstdio> #include <algorithm> #include <cstring> #include <vector> #include <set> using namespace std; const int MAXH = 210; const int MAXW = 65; int H,W; int dx[] = {0, 0, -1, 1}; int dy[] = {1, -1, 0, 0}; char* bin[16]= {"0000","0001","0010","0011","0100","0101","0110","0111" ,"1000","1001","1010","1011","1100","1101","1110","1111"}; char code[7] = "WAKJSD"; 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 nx = x + dx[i], ny = y + dy[i]; if(nx >= 0 && nx < H && ny >= 0 && ny < W && pic[x][y] == pic[nx][ny] && !color[nx][ny]) dfs(nx,ny,col); } } int main() { // freopen("in.txt","r",stdin);// FE int cas = 0; while(scanf("%d%d",&H,&W),H){ 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(pic1[i][j]<='9'&&'0'<=pic1[i][j]) pic1[i][j] -= '0'; else pic1[i][j] -= 'a' - 10; for(int k = 0; k < 4; ++k){//decode pic[i+1][1+(j<<2)+k] = bin[pic1[i][j]][k] - '0'; } } H += 2; W = (W<<2)+2; vector<int> cc; int cnt = 0;//cnt = 1一定是白色背景 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 ; i < cc.size(); ++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; }