1. 程式人生 > >Usaco Training Section 4.4 Frame Up

Usaco Training Section 4.4 Frame Up

有一些長方形邊框疊在一起,求放的順序。

因為每個邊框的每條邊至少會出現一個字母,所以我們可以求出每個邊框的準確位置。然後每次在未用過的邊框中找只包含當前字母和已用字母的邊框,標記為已用過,再把遇到的已用字母向當前字母連邊。最後跑個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;
}