POJ 1128 Frame Stacking(拓扑排序+dfs)

来源:互联网 发布:软考程序员通道 编辑:程序博客网 时间:2024/06/05 20:07

Consider the following 5 picture frames placed on an 9 x 8 array. 
........ ........ ........ ........ .CCC....EEEEEE.. ........ ........ ..BBBB.. .C.C....E....E.. DDDDDD.. ........ ..B..B.. .C.C....E....E.. D....D.. ........ ..B..B.. .CCC....E....E.. D....D.. ....AAAA ..B..B.. ........E....E.. D....D.. ....A..A ..BBBB.. ........E....E.. DDDDDD.. ....A..A ........ ........E....E.. ........ ....AAAA ........ ........EEEEEE.. ........ ........ ........ ........    1        2        3        4        5   

Now place them on top of one another starting with 1 at the bottom and ending up with 5 on top. If any part of a frame covers another it hides that part of the frame below. 

Viewing the stack of 5 frames we see the following. 
.CCC....ECBCBB..DCBCDB..DCCC.B..D.B.ABAAD.BBBB.ADDDDAD.AE...AAAAEEEEEE..



In what order are the frames stacked from bottom to top? The answer is EDABC. 

Your problem is to determine the order in which the frames are stacked from bottom to top given a picture of the stacked frames. Here are the rules: 

1. The width of the frame is always exactly 1 character and the sides are never shorter than 3 characters. 

2. It is possible to see at least one part of each of the four sides of a frame. A corner shows two sides. 

3. The frames will be lettered with capital letters, and no two frames will be assigned the same letter.
Input
Each input block contains the height, h (h<=30) on the first line and the width w (w<=30) on the second. A picture of the stacked frames is then given as h strings with w characters each. 
Your input may contain multiple blocks of the format described above, without any blank lines in between. All blocks in the input must be processed sequentially.
Output
Write the solution to the standard output. Give the letters of the frames in the order they were stacked from bottom to top. If there are multiple possibilities for an ordering, list all such possibilities in alphabetical order, each one on a separate line. There will always be at least one legal ordering for each input block. List the output for all blocks in the input sequentially, without any blank lines (not even between blocks).
Sample Input
98.CCC....ECBCBB..DCBCDB..DCCC.B..D.B.ABAAD.BBBB.ADDDDAD.AE...AAAAEEEEEE..
Sample Output
EDABC
  题意:

给出叠加后的效果图,去判断是按照什么顺序叠加起来的,

规则如下:

(1)    图片宽度均为一个字符,四边均不短于三个字符;

(2)    每张图片四条边当中每条边都能看见一部分;

(3)    每张图片中字母代表对应的图片,任何两张图片中不会有相同的字母。

输出描述:

对输入文件中的每个测试数据,按照从底到顶的顺序(先输出底部被覆盖的图片)输出这些图片的叠加顺序(用图片中的字母代表图片)。如果有多组解,则按照字典序输出每一个解。

思路:

                                                                      

    对于给出叠加后的图形,扫描一遍过后可以得到每一个字母的坐标,因为每一个字母矩形每条边上至少都会有一个点,那么就可以确定矩形的大小和四个关键坐标,根据这四个坐标就可以遍历这个字母矩形。在遍历一个字母矩形(A)的时候,若是这个矩形上出现了其他字母(B)就证明是别的字母覆盖了它本身,B在A上面。

    这样把所有的矩形都弄完可以得到一些关系,这样就可以拓扑排序,但是题目要求多组的话字典序,又需要dfs一遍,这样就解决了。

CODE:

#include<stdio.h>#include<string.h>#include<vector>#include<algorithm>using namespace std;#define N 31#define INF 0x3f3f3f3fint n,m,sum;int alpha[N],indegree[N];//记录多少个字母,每个字母的入度char seq[N],e[N][N];vector<int>v[N];//建立邻接表struct node //四个数值确定矩形的大小和位置{    int xmax,xmin;    int ymax,ymin;} a[N];void build(int s)//建图{    char c;    int i,j,k;    for(k=0; k<s; k++)    {        int j1=a[k].xmin;        int j2=a[k].xmax;        for(i=a[k].ymin; i<=a[k].ymax; i++)//矩形的两个横行        {            if(e[j1][i]!=k+'A')            {                c=e[j1][i];                v[k].push_back(c-'A');                indegree[c-'A']++;            }            if(e[j2][i]!=k+'A')            {                c=e[j2][i];                v[k].push_back(c-'A');                indegree[c-'A']++;            }        }        j1=a[k].ymin;        j2=a[k].ymax;        for(i=a[k].xmin; i<=a[k].xmax; i++)//矩形的两个竖行        {            if(e[i][j1]!=k+'A')            {                c=e[i][j1];                v[k].push_back(c-'A');                indegree[c-'A']++;            }            if(e[i][j2]!=k+'A')            {                c=e[i][j2];                v[k].push_back(c-'A');                indegree[c-'A']++;            }        }    }}void toposort(int k){    if(k==sum)    {        seq[sum]='\0';        printf("%s\n",seq);        return ;    }    for(int i=0; i<sum; i++)    {        if(!indegree[i])        {            seq[k]=i+'A';            indegree[i]--;            for(int j=0; j<v[i].size(); j++)                indegree[v[i][j]]--;            toposort(k+1);            indegree[i]++;            for(int j=0; j<v[i].size(); j++)                indegree[v[i][j]]++;        }    }}int main(){    int i,j;    while(~scanf("%d%d",&n,&m))    {        sum=0;        for(i=0;i<26;i++)            v[i].clear();        memset(alpha,0,sizeof(alpha));        memset(indegree,0,sizeof(indegree));        for(i=0; i<26; i++)        {            a[i].xmax=a[i].ymax=0;            a[i].xmin=a[i].ymin=INF;        }        for(i=0; i<n; i++)            scanf("%s",e[i]);        //扫描一遍地图,确定有多少矩形和每一个矩形的位置         for(i=0; i<n; i++)            for(j=0; j<m; j++)            {                if(e[i][j]!='.')                {                    char c=e[i][j];                    if(!alpha[c-'A'])                    {                        sum++;                        alpha[c-'A']=1;                    }                    if(i>a[c-'A'].xmax)                        a[c-'A'].xmax=i;                    if(i<a[c-'A'].xmin)                        a[c-'A'].xmin=i;                    if(j>a[c-'A'].ymax)                        a[c-'A'].ymax=j;                    if(j<a[c-'A'].ymin)                        a[c-'A'].ymin=j;                }            }        build(sum);        toposort(0);    }    return 0;}