zoukankan      html  css  js  c++  java
  • 图论之拓扑排序 poj1128 Frame Stacking

    题目网址 http://poj.org/problem?id=1128

    思路:遍历找出每一种字母出现的最大和最小的横纵坐标,假如本应出现字母A的地方出现了字母B,那么A一定在字母B之前,这就相当于点A到点B有一条有向边,这样就可以建立一张图进行拓扑排序(拓扑排序不唯一,这里题目还要求输出所有结果,这里就进行简单的深度优先搜索)。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct point
    {
        int maxi,maxj,mini,minj;
    } a[26];             //记录一种字母出现的最大最小坐标
    int n,m;
    int mark[26];        //记录哪些字母出现过
    char map[35][35];    //记录原始地图
    int in[27];          //记录每种字母的入度
    int rec[27][27];     //临接矩阵记录边
    int num[26];         //记录答案
    int depth;           //记录搜索的深度
    void init()          //寻找每种字母出现的最大最小坐标
    {
        for(int i=0; i<26; i++)
            if(mark[i]==1)
            {
                int max_i=-1,max_j=-1,min_i=10000,min_j=10000;
                for(int j=0; j<n; j++)
                    for(int k=0; k<m; k++)
                        if(map[j][k]-'A'==i)
                        {
                            if(max_i<j)
                                max_i=j;
    
                            if(min_i>j)
                                min_i=j;
    
                            if(max_j<k)
                                max_j=k;
    
                            if(min_j>k)
                                min_j=k;
                        }
                a[i].maxi=max_i;
                a[i].maxj=max_j;
                a[i].mini=min_i;
                a[i].minj=min_j;
            }
        return ;
    }
    void check()                  //记录边
    {
        for(int i=0; i<n; i++)
            if(mark[i])
            {
                for(int j=a[i].mini; j<=a[i].maxi; j++)
                {
                    if(map[j][a[i].maxj]!=i+'A')
                        if(rec[map[j][a[i].maxj]-'A'][i]==0)
                        {
                            rec[map[j][a[i].maxj]-'A'][i]=1;
                            in[map[j][a[i].maxj]-'A']++;
                        }
                    if(map[j][a[i].minj]!=i+'A')
                        if(rec[map[j][a[i].minj]-'A'][i]==0)
                        {
                            rec[map[j][a[i].minj]-'A'][i]=1;
                            in[map[j][a[i].minj]-'A']++;
                        }
                }
                for(int j=a[i].minj; j<=a[i].maxj; j++)
                {
                    if(map[a[i].maxi][j]!=i+'A')
                        if(rec[map[a[i].maxi][j]-'A'][i]==0)
                        {
                            rec[map[a[i].maxi][j]-'A'][i]=1;
                            in[map[a[i].maxi][j]-'A']++;
                        }
                    if(map[a[i].mini][j]!=i+'A')
                        if(rec[map[a[i].mini][j]-'A'][i]==0)
                        {
                            rec[map[a[i].mini][j]-'A'][i]=1;
                            in[map[a[i].mini][j]-'A']++;
                        }
                }
            }
        return ;
    }
    void print_num(int Cout)     //输出答案
    {
        for(int i=0; i<Cout; i++)
            printf("%c",num[i]+'A');
        puts("");
    }
    void topo_sort(int Cout)   //拓扑加深搜
    {
        if(depth==Cout)
        {
            print_num(Cout);
            return ;
        }
        for(int i=0; i<26; i++)
            if(in[i]==0&&mark[i])
            {
                num[depth]=i;
                depth++;
                in[i]=-1;
                for (int k = 0; k < 26; k++)
                {
                    if (rec[k][i]==1)
                    {
                        in[k]--;
                    }
                }
                topo_sort(Cout);
                for (int k = 0; k < 26; k++)
                {
                    if (rec[k][i] == 1)
                    {
                        in[k]++;
                    }
                }
                in[i]=0;
                depth--;
            }
        return ;
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            getchar();
            memset(in,0,sizeof(in)); //初始化
            memset(rec,0,sizeof(rec));
            memset(map,0,sizeof(map));
            memset(mark,0,sizeof(mark));
            memset(num,0,sizeof(num));
            for(int i=0; i<n; i++)
                gets(map[i]);
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                    mark[map[i][j]-'A']=1;
            init();
            check();
            int Cout=0;
            depth=0;
            for(int i=0; i<26; i++)  //计算一共出现了几个字母
                if(mark[i])Cout++;
            topo_sort(Cout);
        }
        return 0;
    }
    搬砖啦
  • 相关阅读:
    JavaScript 相关记录
    首页大图淡入淡出效果工具flexslider
    取消chrome浏览器下input和textarea的默认样式;html5默认input内容清除“×”按钮去除办法
    Hibernate入门笔记
    Servlet入门笔记
    父容器利用opacity设置透明后,子元素跟着变透明的解决方案
    overflow:hidden与margin:0 auto之间的冲突
    初识Android Studio
    首页图片滚动效果
    DIV宽度设置成100%,浏览器窗口缩小后,右边出现留白
  • 原文地址:https://www.cnblogs.com/xcantaloupe/p/6623720.html
Copyright © 2011-2022 走看看