Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 3636 | Accepted: 1204 |
Description
........ ........ ........ ........ .CCC....
EEEEEE.. ........ ........ ..BBBB.. .C.C....
E....E.. DDDDDD.. ........ ..B..B.. .C.C....
E....E.. D....D.. ........ ..B..B.. .CCC....
E....E.. D....D.. ....AAAA ..B..B.. ........
E....E.. D....D.. ....A..A ..BBBB.. ........
E....E.. DDDDDD.. ....A..A ........ ........
E....E.. ........ ....AAAA ........ ........
EEEEEE.. ........ ........ ........ ........
1 2 3 4 5
.CCC....
ECBCBB..
DCBCDB..
DCCC.B..
D.B.ABAA
D.BBBB.A
DDDDAD.A
E...AAAA
EEEEEE..
Input
Output
Sample Input
9
8
.CCC....
ECBCBB..
DCBCDB..
DCCC.B..
D.B.ABAA
D.BBBB.A
DDDDAD.A
E...AAAA
EEEEEE..
Sample Output
EDABC
这题和上一篇博客的那道题的做法差不多,就是建图比较麻烦。还有题目保证至少存在一种符合要求的序列,当有多种情况时按字典序由小到大输出所有的情况。
这题的难点是输出所有的拓扑序列,根据题目描述最坏情况有26!中情况(即每一个图片都无重叠部分),刚开始就被它给吓着了,迟迟不敢下手!最后无奈之下暴力的试了一下竟然过了。只能说这题数据太水了,不过话说如果不是这样的话,这题我还真不知道怎么解了,毕竟按照暴力的方法时间复杂度太高了(欢迎哪位大神来分享下较好的算法)。
对于建图,如果不懂的话,可以参照我的上一篇博客,然后最后求拓扑序列就是直接枚举全排列了。对于每一种排列,如果每条边都是从左到右则符合。这题其实也没用求拓扑的算法,主要是根据它的定义做个判断。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int w,h; char image[35][35]; int map[35][35];//邻接表 int flag[26];//记录字母是否出现过 int q[30],cnt;//出现的字母(由小到大) int visit[30];//dfs时的标记数组 int ans[30];//序列 void build() { int i,j,k,l; for(i=1;i<=h;i++) for(j=1;j<=w;j++) { char c=image[i][j]; if(c=='.') continue; if(!flag[c-'A']) { int c1,c2,r;//分别记录左边界、右边界、下边界 flag[c-'A']=1; //左边界 for(k=1;;k++) { for(l=i;l<=h;l++) if(image[l][k]==c) break; if(l<=h) break; } c1=k; //右边界 for(k=w;;k--) { for(l=i;l<=h;l++) if(image[l][k]==c) break; if(l<=h) break; } c2=k; //下边界 for(k=h;;k--) { for(l=c1;l<=c2;l++) if(image[k][l]==c) break; if(l<=c2) break; } r=k; //开始扫描框架上的元素 for(k=c1;k<=c2;k++) { int u=c-'A'; int v=image[i][k]-'A'; if(u!=v) map[u][v]=1; v=image[r][k]-'A'; if(u!=v) map[u][v]=1; } for(k=i;k<=r;k++) { int u=c-'A'; int v=image[k][c1]-'A'; if(u!=v) map[u][v]=1; v=image[k][c2]-'A'; if(u!=v) map[u][v]=1; } } } } //判断每种排列是否是拓扑序列 void dfs(int i) { if(i==cnt) { for(int j=0;j<cnt;j++) printf("%c",ans[j]+'A'); printf("\n"); return; } for(int j=0;j<cnt;j++) if(!visit[q[j]]) { ans[i]=q[j]; bool state=true; for(int k=i;k>0&&state;k--) for(int l=0;l<k;l++) if(map[ans[k]][ans[l]]) { state=false; break; } if(!state) continue; visit[q[j]]=1; dfs(i+1); visit[q[j]]=0; } } int main() { int i,j; while(~scanf("%d%d",&h,&w)) { for(i=1;i<=h;i++) { getchar(); for(j=1;j<=w;j++) image[i][j]=getchar(); } memset(map,0,sizeof(map)); memset(flag,0,sizeof(flag)); build();//建图 cnt=0; for(i=0;i<26;i++) if(flag[i]) { q[cnt++]=i; visit[i]=0; } dfs(0);//枚举 } return 0; }