有一些长方形边框叠在一起,求放的顺序。
因为每个边框的每条边至少会出现一个字母,所以我们可以求出每个边框的准确位置。然后每次在未用过的边框中找只包含当前字母和已用字母的边框,标记为已用过,再把遇到的已用字母向当前字母连边。最后跑个dfs,求拓扑排序。
细节挺多的,一开始没想到拓扑排序,过了好一会儿才想到。然后p数组开小了,怎么也没发现,在usaco上竟然跑出来是wa,而不是re!!!在我的电脑竟然没报错,输出的答案居然还是对的!!!……
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 2147483647
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
using namespace std;
char a[35][35];
bool vis[35],used[35],visit[35];
int minx[35],miny[35],maxx[35],maxy[35],d[35],sum,p[905],num[35],ans[35],rd[35],b[35][35];
set<string> s;
inline void dfs(int n){
if(n>sum){
string str="";
for(int i=sum;i;--i){
char c=d[ans[i]]+64;
str+=c;
}
s.insert(str);
return;
}
for(int i=1;i<=sum;++i){
if(!rd[i]&&!visit[i]){
for(int j=1;j<=sum;++j) rd[j]-=b[i][j];
visit[i]=1;
ans[n]=i;
dfs(n+1);
for(int j=1;j<=sum;++j) rd[j]+=b[i][j];
visit[i]=0;
}
}
}
int main()
{
ios::sync_with_stdio(false);
freopen("frameup.in","r",stdin);
freopen("frameup.out","w",stdout);
int n,m;
cin>>n>>m;
for(int i=1;i<=26;++i) minx[i]=miny[i]=40;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
cin>>a[i][j];
if(a[i][j]=='.') continue;
int x=a[i][j]-64;
minx[x]=min(minx[x],i);
miny[x]=min(miny[x],j);
maxx[x]=max(maxx[x],i);
maxy[x]=max(maxy[x],j);
if(!vis[x]) vis[x]=1,d[++sum]=x,num[x]=sum;
}
while(1){
bool ok=0;
for(int i=1;i<=sum;++i){
if(used[d[i]]) continue;
char c=d[i]+64;
int x1=minx[d[i]],x2=maxx[d[i]],y1=miny[d[i]],y2=maxy[d[i]];
bool f=1;
int t=0;
for(int j=y1;j<=y2;++j)
if(a[x1][j]!=c&&!used[a[x1][j]-64]){f=0;break;}
else if(used[a[x1][j]-64]) p[++t]=num[a[x1][j]-64];
if(!f) continue;
for(int j=y1;j<=y2;++j)
if(a[x2][j]!=c&&!used[a[x2][j]-64]){f=0;break;}
else if(used[a[x2][j]-64]) p[++t]=num[a[x2][j]-64];
if(!f) continue;
for(int j=x1+1;j<=x2-1;++j)
if(a[j][y1]!=c&&!used[a[j][y1]-64]){f=0;break;}
else if(used[a[j][y1]-64]) p[++t]=num[a[j][y1]-64];
if(!f) continue;
for(int j=x1+1;j<=x2-1;++j)
if(a[j][y2]!=c&&!used[a[j][y2]-64]){f=0;break;}
else if(used[a[j][y2]-64]) p[++t]=num[a[j][y2]-64];
if(!f) continue;
ok=1;
used[d[i]]=1;
for(int j=1;j<=t;++j) ++b[p[j]][num[d[i]]],++rd[num[d[i]]];
}
if(!ok) break;
}
dfs(1);
while(!s.empty()){
cout<<*s.begin()<<'\n';
s.erase(s.begin());
}
return 0;
}