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;
}

猜你喜欢

转载自blog.csdn.net/qq_36911709/article/details/82259079
今日推荐