题目给出一个方块互相叠加的图,求出所有可能的重叠顺序
解题思路:按照NOCOW的题解建好图之后,就是求一个拓扑排序的所有解了,搜索的时候按照字典序搜索就可以按照字典序求出所有的答案,这个题唯一的难点就是输出拓扑图所有的解,以前按照删边求的方法只能求一种解,脑筋不知道怎么就不灵光了,翻了资料才知道怎么求,其实也简单的。PS:表示对USACO好无语,数组越界报超时,好无辜的debug好久
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<fstream>
#define zout cout
#define maxn 140
#define M(a) memset((a),0,sizeof(a))
using namespace std;
ifstream fin("frameup.in");
ofstream fout("frameup.out");
struct Ch
{
int mix,miy,mx,my;
Ch()
{
mx=my=-100;
mix=miy=100;
}
}; //储存每个矩形的最小坐标和最大坐标
Ch cor[100];
int n,m;
int g[maxn][maxn]; //图的邻接矩阵存储
char f[maxn][maxn]; //输入的字符矩阵
int apl[maxn],a[maxn],result[maxn*100][maxn];
bool vis[maxn];
int tot,ir;
bool init()
{
if(fin>>n>>m)
{
ir=0;
M(g);M(apl);
tot=0;
for(int i=0;i<n;i++)
fin>>f[i];
return true;
}
return false;
}
void upd(int u,int x,int y) //更新每个矩阵的临界坐标函数
{
Ch & t=cor[u];
if(x>t.mx)t.mx=x;
if(y>t.my)t.my=y;
if(x<t.mix)t.mix=x;
if(y<t.miy)t.miy=y;
}
void build_graph() //建图过程,参考nocow
{
for(int i=0;i<26;i++)
{
Ch & t = cor[i];
if(apl[i])
{
int v,u = i;
for(int x=t.mix;x<=t.mx;x++)
{
if(f[x][t.miy]!=i+'A')
{
v=f[x][t.miy]-'A';
g[u][v]=1;
}
if(f[x][t.my]!=i+'A')
{
v=f[x][t.my]-'A';
g[u][v]=1;
}
}
for(int y=t.miy;y<=t.my;y++)
{
if(f[t.mx][y]!=i+'A')
{
int v=f[t.mx][y]-'A';
g[u][v]=1;
}
if(f[t.mix][y]!=i+'A')
{
int v=f[t.mix][y]-'A';
g[u][v]=1;
}
}
}
}
}
int isStart(int st) //判断一个点St的入度是否为0,是返回true,不是返回false
{
bool ff[maxn];
M(ff);
int e=0;
for(int i=0;i<26;i++)
{
if(apl[i])
{
e=0;
for(int j=0;j<26;j++)
if(g[i][j])
{
if(j==st)return false;
}
}
}
return true;
}
void op()
{
char ch;
for(int i=0;i<ir;i++)
{
for(int j=0;j<tot;j++)
{
ch='A'+result[i][j];
zout<<ch;
}
zout<<endl;
}
}
void dfs(int u,int a[],int dep) //改进后的dfs求拓扑排序,数组a记录了深搜树到达叶子节点的路径,也就是答案
{
if(dep==tot)
{
for(int i=0;i<tot;i++)
result[ir][i]=a[i];
ir++;
}
int f=0;
for(int i=0;i<26;i++)
{
if(apl[i]&&isStart(i))
{
f=1;
apl[i]=0;
a[dep]=i;
dfs(i,a,dep+1);
apl[i]=1;
}
}
if(f)return;
for(int i=0;i<26;i++)
{
if((apl[i]&&g[u][i]))
{
apl[i]=0;
a[dep]=i;
dfs(i,a,dep+1);
apl[i]=1;
}
}
}
void slove()
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(f[i][j]!='.')
apl[f[i][j]-'A']=1;
tot=0;
for(int i=0;i<26;i++)
if(apl[i])tot++;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
if(f[i][j]!='.')
{
upd(f[i][j]-'A',i,j);
}
}
build_graph();
for(int i=0;i<26;i++)
{
if(apl[i]&&isStart(i))
{
apl[i]=0;
a[0]=i;
dfs(i,a,1);
apl[i]=1;
}
}
op();
}
int main()
{
init();
slove();
return 0;
}