# UVa 1103 - Ancient Messages --- # 題目大意 給定H個16進位、長度為W的字串,用其二進位表示6種象形文字。如果是同一個象形文字,則黑色的部分會上下左右相連,而象形文字間不會相碰。要求辨識圖形中所有的象形文字,並按照字典序輸出。 --- # 題解 可以發現每種文字含有的空格數不同,因此可以藉由空格數辨識文字。 做三種BFS。首先將象形文字外部的空白去除,接著將文字的黑色部分跑一遍,此時碰到內部的白色格時再做一次BFS並記錄有幾塊白色。 --- ```=C++ #include <bits/stdc++.h> #define ll long long #define pb push_back #define pf push_front #define ft first #define sec second #define pr pair<int,int> #define ISCC ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; int t ,n ,m ,vis[205][205] ,dir[][2] = {{1,0},{0,1},{-1,0},{0,-1}} ,sum ,cas; string g[205] ,s ,ans; string trans(int pos) //16進位轉2進位 { string res = ""; int tp = ('0'<=s[pos] && s[pos]<='9')?(s[pos]-'0'):(10+s[pos]-'a'); for(int i=0 ;i<4 ;i++) res = ((tp&(1<<i))?'1':'0') + res; return res; } void bfs(pr pos ,char type ,int sol) //sol代表要不要數區塊數 { queue<pr> que; que.push(pos); while(!que.empty()) { pr now = que.front(); que.pop(); if(vis[now.ft][now.sec]) continue; vis[now.ft][now.sec] = 1; for(int i=0 ;i<4 ;i++) { int x = now.ft+dir[i][0] ,y = now.sec+dir[i][1]; if(x<0 || y<0 || x>n+1 || y>4*m+1 || vis[x][y]) continue; if(sol && g[x][y]=='0') { sum++; bfs({x,y} ,'0' ,0); } if(g[x][y] != type) continue; que.push({x,y}); } } } int main() { map<int ,char> mp; mp[1] = 'A'; mp[3] = 'J'; mp[5] = 'D'; mp[4] = 'S'; mp[0] = 'W'; mp[2] = 'K'; while(cin >> n >> m && n && m) { getchar(); string tp; tp = ""; for(int i=1 ;i<=4*m+2 ;i++) tp += '0'; //用0圍一圈邊界 g[0] = g[n+1] = tp; memset(vis,0,sizeof(vis)); ans = ""; for(int i=1 ;i<=n ;i++) { getline(cin ,s); tp = ""; for(int j=0 ;j<m ;j++) tp += trans(j); g[i] = '0'+tp+'0'; } bfs({0,0} ,'0' ,0); //去除文字外的空白 for(int i=1 ;i<=n ;i++) for(int j=1 ;j<=4*m ;j++) if(g[i][j] == '1' && !vis[i][j]) { sum = 0; //紀錄白色區塊數 bfs({i,j} ,'1' ,1); ans += mp[sum]; } sort(ans.begin() ,ans.end()); //照字典序排好 printf("Case %d: %s\n",++cas ,ans.c_str()); } return 0; } ```