Usaco Training Section 4.4 Frame Up
阿新 • • 發佈:2018-11-12
有一些長方形邊框疊在一起,求放的順序。
因為每個邊框的每條邊至少會出現一個字母,所以我們可以求出每個邊框的準確位置。然後每次在未用過的邊框中找只包含當前字母和已用字母的邊框,標記為已用過,再把遇到的已用字母向當前字母連邊。最後跑個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; }