链接:点击打开链接
题意:给出一个h*w的图形,将一些字母组成的图片重叠在一起,输出所有的可能
代码:
#include <set> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; int N,M,cnt; int vis[505],que[505]; int head[505],indegree[505]; char c[105],s[105][105]; struct node{ int to,next; }G[505]; void addedge(int u,int v){ G[cnt].to=v; G[cnt].next=head[u]; head[u]=cnt++; } void dfs(int sum){ int i,j; if(sum==N){ for(i=0;i<N;i++) printf("%c",c[que[i]]); printf("\n"); return ; } for(i=1;i<=N;i++){ if(indegree[i]==0&&vis[i]==0){ vis[i]=1; que[sum]=i; for(j=head[i];j!=-1;j=G[j].next) indegree[G[j].to]--; dfs(sum+1); vis[i]=0; for(j=head[i];j!=-1;j=G[j].next) indegree[G[j].to]++; } } } //输出所有拓扑序 struct edge{ int l1,r1,l2,r2; }tmp[505]; int main(){ int i,j,p,q,k,h,w,sign; while(scanf("%d%d",&h,&w)!=EOF){ cnt=0; set<char> se; set<char>::iterator ite; memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head)); memset(indegree,0,sizeof(indegree)); for(i=1;i<=h;i++) for(j=1;j<=w;j++){ scanf(" %c",&s[i][j]); if(s[i][j]>='A'&&s[i][j]<='Z') se.insert(s[i][j]); } k=1; for(ite=se.begin();ite!=se.end();ite++){ tmp[k].l1=tmp[k].r1=INF; tmp[k].l2=tmp[k].r2=0; c[k++]=*ite; } //找出所有的字母 N=se.size(); for(i=1;i<=h;i++) for(j=1;j<=w;j++){ for(k=1;k<=N;k++){ if(s[i][j]==c[k]){ tmp[k].l1=min(tmp[k].l1,i); tmp[k].r1=min(tmp[k].r1,j); tmp[k].l2=max(tmp[k].l2,i); tmp[k].r2=max(tmp[k].r2,j); } } } //求出所有相框的左上角和右上角 for(i=1;i<=N;i++){ for(j=1;j<=N;j++){ if(i!=j){ //找出每张图片的可能重叠情况并建图 for(q=tmp[i].r1;q<=tmp[i].r2;q++) if(s[tmp[i].l1][q]==c[j]){ addedge(i,j); indegree[j]++; goto next; } for(q=tmp[i].r1;q<=tmp[i].r2;q++) if(s[tmp[i].l2][q]==c[j]){ addedge(i,j); indegree[j]++; goto next; } for(q=tmp[i].l1;q<=tmp[i].l2;q++) if(s[q][tmp[i].r1]==c[j]){ addedge(i,j); indegree[j]++; goto next; } for(q=tmp[i].l1;q<=tmp[i].l2;q++) if(s[q][tmp[i].r2]==c[j]){ addedge(i,j); indegree[j]++; goto next; } } next:; } } dfs(0); } return 0; }