题意:给出一张图,它是由一系列字母框按一定顺序从下到上摆放,因此上面的字母框会覆盖一部分下面的字母框,确保每个字母框的四条边都至少会出现一个点,要求输出所有可行的摆放顺序,字典序从小到大输出。
首先可以根据每个字母出现的位置确定每个字母的四条边,然后根据露出来的字母可以确定哪个字母在其他字母上面,所以就可以建出拓扑序的图,由于要输出所有解,所以需要 dfs 来解决,至于字典序只要按照 dfs 的遍历顺序从字母小的到字母大的就行了。
1 #include<stdio.h>
2 #include<string.h>
3
4 char s[35][35];
5 int l[26],r[26],u[26],d[26];
6 int ma[26][26],id[26],n,vis[26],v[26];
7 char ans[50];
8
9 void get(int i,int j,int k){
10 if(s[i][j]!='A'+k){
11 int c=s[i][j]-'A';
12 if(!ma[k][c]){
13 ma[k][c]=1;
14 id[c]++;
15 }
16 }
17 }
18
19 void dfs(int ss,int t){
20 ans[t]=ss+'A';
21 v[ss]=1;
22 if(t==n){
23 for(int i=1;i<=n;++i)printf("%c",ans[i]);
24 printf("
");
25 v[ss]=0;
26 return;
27 }
28 int que[28],cnt=0;
29 for(int i=0;i<26;++i){
30 if(ma[ss][i])id[i]--;
31 if(vis[i]&&!id[i]&&!v[i])que[++cnt]=i;
32 }
33 for(int i=1;i<=cnt;++i)dfs(que[i],t+1);
34 for(int i=0;i<26;++i)if(ma[ss][i])id[i]++;
35 v[ss]=0;
36 }
37
38 int main(){
39 int h,w;
40 while(scanf("%d%d",&h,&w)!=EOF){
41 n=0;
42 memset(ma,0,sizeof(ma));
43 for(int i=0;i<26;++i){
44 l[i]=u[i]=35;
45 r[i]=d[i]=0;
46 id[i]=vis[i]=v[i]=0;
47 }
48 for(int i=1;i<=h;++i)scanf("%s",s[i]+1);
49 for(int i=1;i<=h;++i){
50 for(int j=1;j<=w;++j){
51 if(s[i][j]!='.'){
52 int c=s[i][j]-'A';
53 if(!vis[c]){
54 vis[c]=1;
55 n++;
56 }
57 if(i<u[c])u[c]=i;
58 if(i>d[c])d[c]=i;
59 if(j<l[c])l[c]=j;
60 if(j>r[c])r[c]=j;
61 }
62 }
63 }
64 for(int k=0;k<26;++k){
65 if(l[k]==35)continue;
66 int i,j;
67 i=u[k];
68 for(j=l[k];j<=r[k];++j)get(i,j,k);
69 i=d[k];
70 for(j=l[k];j<=r[k];++j)get(i,j,k);
71 j=l[k];
72 for(i=u[k]+1;i<d[k];++i)get(i,j,k);
73 j=r[k];
74 for(i=u[k]+1;i<d[k];++i)get(i,j,k);
75 }
76 for(int i=0;i<26;++i){
77 if(vis[i]&&!id[i])dfs(i,1);
78 }
79 }
80 return 0;
81 }