题意:
有一层层火焰图,不同火焰图用不同大写字母表示,一个火焰图是矩形的,给出整张图,问火焰图放的顺序
题解:
A火焰出现在B火焰的边框上说明A火焰在B火焰的上面,我们可以记录出每个火焰的左上角与右下角的顶点,这样就可以遍历他的边框进行建边
然后是按字典序输出所有方案,瞬间懵逼,联想到前两天刚做的一道题,只要逆向建边即可dfs回溯输出
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int pos1[30][2],pos2[30][2],n,m,ans[30],in[30],cnt,head[30],vis[30],NE;
char g[40][40];
struct node
{
int v,next;
}edge[10000];
void add(int u,int v)
{
edge[NE].v=v;
edge[NE].next=head[u];
head[u]=NE++;
}
void dfs(int id,int depth)
{
ans[depth]=id;
if(depth==cnt){for(int i=1;i<=cnt;i++)printf("%c",ans[i]+'A');printf("\n");return;}
vis[id]=1;
for(int i=head[id];i!=-1;i=edge[i].next)
in[edge[i].v]--;
for(int i=0;i<26;i++)
if(in[i]==0&&!vis[i])dfs(i,depth+1);
for(int i=head[id];i!=-1;i=edge[i].next)
in[edge[i].v]++;
vis[id]=0;
}
int main()
{//freopen("C:\\Users\\Administrator\\Desktop\\input.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=1;i<=n;i++)scanf("%s",g[i]+1);
NE=0;
memset(pos1,inf,sizeof(pos1));
memset(head,-1,sizeof(head));
memset(pos2,0,sizeof(pos2));
memset(in,-1,sizeof(in));
cnt=0;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
if(g[i][j]>='A'&&g[i][j]<='Z'){
int x=g[i][j]-'A';
in[x]=0;
pos1[x][0]=min(pos1[x][0],i);
pos1[x][1]=min(pos1[x][1],j);
pos2[x][0]=max(pos2[x][0],i);
pos2[x][1]=max(pos2[x][1],j);
}
for(int i=0;i<26;i++){
memset(vis,0,sizeof(vis));
vis[i]=1;
if(!pos2[i][0])continue;
cnt++;
for(int j=pos1[i][1];j<=pos2[i][1];j++){
int x=g[pos1[i][0]][j]-'A';
if(!vis[x]){add(i,x);in[x]++;vis[x]=1;}
}
for(int j=pos1[i][1];j<=pos2[i][1];j++){
int x=g[pos2[i][0]][j]-'A';
if(!vis[x]){add(i,x);in[x]++;vis[x]=1;}
}
for(int j=pos1[i][0];j<=pos2[i][0];j++){
int x=g[j][pos1[i][1]]-'A';
if(!vis[x]){add(i,x);in[x]++;vis[x]=1;}
}
for(int j=pos1[i][0];j<=pos2[i][0];j++){
int x=g[j][pos2[i][1]]-'A';
if(!vis[x]){add(i,x);in[x]++;vis[x]=1;}
}
}
for(int i=0;i<26;i++){
memset(vis,0,sizeof(vis));
if(in[i]==0)dfs(i,1);
}
}
return 0;
}