POJ 1128 拓撲排序
阿新 • • 發佈:2018-12-18
題意:
給出一個由字母邊框拼起來的圖,問這個圖是又多少種構造方式,輸出所有的方式。
分析:
如果這個字母邊框中有其他的字母,則可以看成是一個這個字母到那個字母的一條邊。然後用拓撲排序輸出就可以了。
#include<cstdio> #include<cstring> using namespace std; int h,w; char g[35][35]; bool mp[35][35]; bool vis[35]; int ans[35]; bool flag[35]; int q[35],cnt; void build(){ int i,j,k,l; for(i=1;i<=h;i++){ for(j=1;j<=w;j++){ char c=g[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( g[l][k]==c ){ break; } } if( l<=h ) break; } c1=k; //右邊界 for(k=w;;k--){ for(l=i;l<=h;l++){ if(g[l][k]==c) break; } if(l<=h) break; } c2=k; //下邊界 for(k=h;;k--){ for(l=c1;l<=c2;l++){ if(g[k][l]==c) break; } if(l<=c2) break; } r=k; //掃描邊框 for(k=c1;k<=c2;k++){ int u=c-'A'; int v=g[i][k]-'A'; if(u!=v){ mp[u][v]=1; } v=g[r][k]-'A'; if(u!=v) mp[u][v]=1; } for(k=i;k<=r;k++){ int u=c-'A'; int v=g[k][c1]-'A'; if(u!=v) mp[u][v]=1; v=g[k][c2]-'A'; if(u!=v) mp[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(vis[q[j]]) continue; ans[i]=q[j]; bool state=true; for(int k=i;k>0&&state;k--){ for(int l=0;l<k;l++){ if(mp[ans[k]][ans[l]]){ state=0; break; } } } if(!state) continue; vis[q[j]]=1; dfs(i+1); vis[q[j]]=0; } } int main(){ while(~scanf("%d%d",&h,&w)){ for(int i=1;i<=h;i++){ scanf("%s",g[i]+1); } memset(mp,0,sizeof mp); memset(flag,0,sizeof flag); build(); cnt=0; for(int i=0;i<26;i++){ if(flag[i]){ q[cnt++]=i; vis[i]=0; } } dfs(0); } return 0; }