起初学习dfs的时候 看不懂这个题目 回过头来今天看的时候思路相对比较清晰了。但还是想不到怎么处理 查询有多少个空白洞。并且一个图中还有好多个象形字符。网上思路是 在周围扩展一圈0,使得文字之外的所有0 都连通,一次dfs标记所有文字之外的0为-1。然后遍历图,发现1就沿着有1 的路径dfs2,在这个过程中,如果发现0,那么必然是文字内部的空洞,此时把空洞dfs 置为-1,标记以后不再走。那么发现几次0就有几个空洞在文字中。那么每一次的dfs2,就处理了一个象形文字。cnt的值就是空洞的个数即文字特征量。感觉这题目相当有价值。
有一处值得学习的地方,字符串常量的运用。
奇怪的地方时在hdu oj上提交 是栈溢出,而在uva上却过了。
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int INF=210; int n,m,cnt; char cn[6]= {'A','D','J','K','S','W'}; char str[]= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; int dir[][4]= {{-1,0},{0,-1},{1,0},{0,1}}; int G[INF][INF]; int s[16][4]= { {0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1}, {0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1}, {1,0,0,0},{1,0,0,1},{1,0,1,0},{1,0,1,1}, {1,1,0,0},{1,1,0,1},{1,1,1,0},{1,1,1,1} }; void input() { char ch; memset(G,0,sizeof(G)); for(int i=1; i<=n; i++) { getchar(); int len=1; for(int j=1; j<=m; j++) { scanf("%c",&ch); for(int k=0; k<16; k++) { if(ch==str[k]) { for(int t=0; t<4; t++) G[i][len++]=s[k][t]; break; } } } } } bool inG(int x,int y) { if(x>=0&&x<=n+1&&y>=0&&y<=m+1) return 1; return 0; } void dfs(int x,int y) { if(!inG(x,y)||G[x][y]!=0) return ; G[x][y]=-1; for(int i=0; i<4; i++) { int tx=x+dir[i][0]; int ty=y+dir[i][1]; dfs(tx,ty); } } void dfs2(int x,int y) { if(!inG[x][y]||G[x][y]==-1) return ; if(!G[x][y]) { dfs(x,y); cnt++; return ; } G[x][y]=-1; for(int i=0; i<4; i++) { int tx=x+dir[i][0]; int ty=y+dir[i][1]; dfs2(tx,ty); } } int main() { int ca=1; int num[10]; while(scanf("%d%d",&n,&m)==2&&n+m) { memset(G,0,sizeof(G)); memset(num,0,sizeof(num)); input(); m*=4; dfs(0,0); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(G[i][j]==1) { cnt=0; dfs2(i,j); if(cnt==0) num[5]++; else if(cnt==2) num[3]++; else if(cnt==3) num[2]++; else if(cnt==4) num[4]++; else if(cnt==1) num[0]++; else num[1]++; } } } printf("Case %d: ",ca++); for(int i=0; i<6; i++) while(num[i]--) printf("%c",cn[i]); printf("\n"); } return 0; }
时间: 2024-12-24 09:10:20