http://poj.org/problem?id=1128
题目大意:
如图有5个9*8的区域
上面分别存在由相同的字母围成的长方形;
把他们依次覆盖起来,便形成了如下的图形
//////可以大致看出有的字母方框的字母被另外的一些字母覆盖了起来
输出从下到上被覆盖的字母的顺序,例如此图为EDABC
大致思路:这种问题稍稍思考便知道是一个拓扑排序的问题,但是真正编码后便感觉还缺了一些东西,对,就是建图!模版谁都会用,但是真正牛人就是牛在知道如何搭建使用模版的环境。如图怎么在原来杂乱无章的map基础上归纳出字母之间的上下级关系便是这道题目的重点所在。
做法是这样:
依次遍历整个map,找到一个字母后便针对这个字母,求出其所在方框的范围,并找出的其范围内的其他字母,建立指向原先字母的边。对图中所有字母重复这个过程,便得到了一个有向图,并对这个有向图拓扑排序,便得到了答案
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 char str[100]; 6 char map[100][100]; 7 bool vis[100]; 8 int in[100],edge[100][100],r,c; 9 int lx,uy,rx,dy,num; 10 void find(int y,int x){ 11 char ch=map[y][x]; 12 lx=uy=10000; 13 rx=dy=-1; 14 for(int i=0;i<r;i++){ 15 for(int j=0;j<c;j++){ 16 if(map[i][j]==ch){ 17 if(i<uy)uy=i; 18 if(i>dy)dy=i; 19 if(j<lx)lx=j; 20 if(j>rx)rx=j; 21 } 22 } 23 } 24 } 25 void buildmap(){ 26 int i,j,k; 27 num=0; 28 for(i=0;i<r;i++){ 29 for(j=0;j<c;j++){ 30 if(map[i][j]=='.'||in[map[i][j]-'A']!=-1)continue; 31 num++; 32 in[map[i][j]-'A']=0; 33 char ch=map[i][j]; 34 find(i,j); 35 for(k=lx;k<=rx;k++){ 36 if(map[uy][k]!=ch)edge[ch-'A'][map[uy][k]-'A']=1; 37 if(map[dy][k]!=ch)edge[ch-'A'][map[dy][k]-'A']=1; 38 } 39 for(k=uy;k<=dy;k++){ 40 if(map[k][lx]!=ch)edge[ch-'A'][map[k][lx]-'A']=1; 41 if(map[k][rx]!=ch)edge[ch-'A'][map[k][rx]-'A']=1; 42 } 43 } 44 } 45 for(i=0;i<27;i++){ 46 for(j=0;j<27;j++){ 47 if(edge[i][j]) 48 in[j]++; 49 } 50 } 51 } 52 void dfs(char *s,int cnt){ 53 if(cnt==num){ 54 printf("%s ",str); 55 return; 56 } 57 int i,j; 58 for(i=0;i<27;i++){ 59 if(in[i]==0&&!vis[i]){ 60 str[cnt]=i+'A'; 61 vis[i]=1; 62 for(j=0;j<27;j++){ 63 if(edge[i][j])--in[j]; 64 } 65 dfs(s,cnt+1); 66 vis[i]=0; 67 for(j=0;j<27;j++){ 68 if(edge[i][j])++in[j]; 69 } 70 } 71 } 72 } 73 int main(){ 74 int i,j; 75 while(scanf("%d%d",&r,&c)!=EOF){ 76 memset(str,0,sizeof(str)); 77 memset(vis,0,sizeof(vis)); 78 memset(in,-1,sizeof(in)); 79 memset(edge,0,sizeof(edge)); 80 for(i=0;i<r;i++)scanf("%s",map[i]); 81 buildmap(); 82 dfs(str,0); 83 } 84 return 0; 85 }