zoukankan      html  css  js  c++  java
  • POJ1128 Frame Stacking(拓扑排序)

    题目链接:http://poj.org/problem?id=1128

    题意:给你一个平面,里面有些矩形(由字母围成),这些矩形互相有覆盖关系,请从求出最底层的矩形到最上层的矩形的序列,如果存在多种序列,答案按照字典序依次输出。

    思路:这道题的难点在建图,利用矩形之间的覆盖关系建图,说着容易,实际上仔细想想不太容易。由于矩形的任意一个边界不会完全被覆盖,所以我们可以确定一个矩形的上下左右边界,然后对每个矩形的上下左右边界扫一遍,看是否被其他字母所覆盖,利用覆盖关系建图。这里无法利用队列的方式拓扑排序,因为要输出所有的序列,所以dfs的方式更为出色,具体的注释都写在代码里面了。

    //Author: xiaowuga
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <ctime>
    #include <map>
    #include <bitset>
    #include <cctype>
    #define maxx INT_MAX
    #define minn INT_MIN
    #define inf 0x3f3f3f3f
    #define mem(s,ch) memset(s,ch,sizeof(s))
    #define da cout<<"da"<<endl
    #define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    #define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    const long long N=35;
    using namespace std;
    typedef long long LL;
    int L[N],R[N],U[N],D[N],in[N],vis[N],v[N];
    //L左边界数组,R有边界数组,U上边界数组,D下边界数组
    //vis字母存在数组,v是dfs中是否访问数组
    char pic[N][N],ans[N];
    int p[N][N];
    int n,m,ct;
    //初始化
    void init(){
        ct=0;//存在字母总数量初始化为0
        mem(in,0);//入度数组初始化为0
        mem(vis,0);//字母存在数组初始化为0
        mem(v,0);
        mem(p,0);//邻接矩阵初始化为0
        //上左边界最大化,下右边界最小化
        mem(L,inf);mem(U,inf);mem(R,-1);mem(D,-1);
    }
    void make_g(int i,int j,int k){
        int t=pic[i][j]-'A';
        if(k!=t){
            if(!p[k][t]) {p[k][t]=1;in[t]++;}
        }
    }
    void dfs(int x,int y){
        ans[y]=x+'A';
        v[x]=1;//标记为访问过
        if(y==ct){//全部字母已经排好拓扑序
            for(int i=1;i<=ct;i++) cout<<ans[i];cout<<endl;//输出
            v[x]=0;//恢复
            return ;
        }
        int q[N],num=0;
        //i从0-26保证了字典序
        for(int i=0;i<26;i++){
            if(p[x][i]) --in[i];//存在连接则连接减少入度
            if(vis[i]&&!in[i]&&!v[i]) q[num++]=i;//存在连接且入度减为0,且未访问
        }
        //对所有后续节点进行dfs
        for(int i=0;i<num;++i) dfs(q[i],y+1);
        for(int i=0;i<26;i++) if(p[x][i]) in[i]++;//恢复
        v[x]=0;//恢复
    }
    void topo(){
        for(int i=0;i<26;++i) if(vis[i]&&!in[i]) dfs(i,1);
    }
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);
        while(cin>>n>>m){
            init();
            //输入整个图形并确定每个矩形的上下左右边界
            for(int i=0;i<n;++i) for(int j=0;j<m;++j){
                cin>>pic[i][j];
                if(pic[i][j]!='.'){
                    int t=pic[i][j]-'A';
                    if(!vis[t]){ vis[t]=1;ct++;}
                    L[t]=min(L[t],j);
                    R[t]=max(R[t],j);
                    U[t]=min(U[t],i);
                    D[t]=max(D[t],i);
                }
            }
            for(int k=0;k<26;k++){
               if(vis[k]){
                    int i,j;
                    i=U[k];//上边界上
                    for(j=L[k];j<=R[k];j++) make_g(i,j,k);
                    i=D[k];//下边界上
                    for(j=L[k];j<=R[k];j++) make_g(i,j,k);
                    j=L[k];//左边界上
                    for(i=U[k]+1;i<D[k];i++) make_g(i,j,k);
                    j=R[k];//右边界上
                    for(i=U[k]+1;i<D[k];i++) make_g(i,j,k);
               } 
            }
            topo(); 
        } 
        return 0;
    }
    View Code
  • 相关阅读:
    LeetCode 1110. Delete Nodes And Return Forest
    LeetCode 473. Matchsticks to Square
    LeetCode 886. Possible Bipartition
    LeetCode 737. Sentence Similarity II
    LeetCode 734. Sentence Similarity
    LeetCode 491. Increasing Subsequences
    LeetCode 1020. Number of Enclaves
    LeetCode 531. Lonely Pixel I
    LeetCode 1091. Shortest Path in Binary Matrix
    LeetCode 590. N-ary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/xiaowuga/p/7231750.html
Copyright © 2011-2022 走看看