Frame Stacking(拓扑排序)

题目链接:http://acm.tju.edu.cn/toj/showp1076.html1076.   Frame Stacking


Time Limit: 1.0 Seconds   Memory Limit: 65536K
Total Runs: 145   Accepted Runs: 54


Consider the following 5 picture frames placed on an 9 x 8 array.

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.

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 DATA

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.

Example input:

9
8
.CCC....
ECBCBB..
DCBCDB..
DCCC.B..
D.B.ABAA
D.BBBB.A
DDDDAD.A
E...AAAA
EEEEEE..

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 DATA

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).

Example Output:

EDABC题目大意:给定一个摞起来的照片图片,输出照片排放的位置,如果有多种放法的话按字典序从小到大输出所有的解题解,这是一个很好的拓扑排序的题,题目中说了每个相片的每条边肯定会漏出至少一个字母,所以很容易确定每个相片的位置,及找到这个相片的横坐标和纵坐标的最左端和最右端,最上端,最下端的值在处理的时候不要忘记对‘.‘的处理,还有从A~Z不是每个字母都会出现。建图的时候因为这个图有很多的重边,而且边数不多的时候最好用矩阵存储,在拓扑排序的时候因为是要输出所有的解,所以使用dfs最好。下面代码中有详细的注释
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<algorithm>
  6 using namespace std;
  7 #define N 110
  8 #define INF 0x1fffffff
  9
 10 struct Node{
 11     int x1,y1,x2,y2;//x1,y1是最下和最左的点
 12     bool flag;//标记一个字母是否出现过
 13     void init(){//初始化所有点的时候找最大的时候初始化成最小,找最小的时候初始化成最大,才可以不断更新
 14         flag = 0;
 15         x1 = y1 = INF;
 16         x2 = y2 = -INF;
 17     }
 18 }node[26];
 19 int n , m;
 20 char mp[N][N];//保存一张图
 21 int g[26][26];//建立关系图
 22 int in[26];//入度
 23 int vis[26];//是否访问过
 24 void add(int u , int v)
 25 {
 26     g[u][v]=1;
 27 }
 28 int total;
 29 void dfs(int cnt , string s)
 30 {
 31     if(cnt==total) printf("%s\n",s.c_str());//dfs当已经把所有的字母顺序都访问过了后就不再进行搜索了
 32     for(int i= 0 ;i < 26 ;i++)
 33     {
 34         if(node[i].flag == 1&&!vis[i]&&in[i]==0)//注意考虑这个字母没有出现的第一个条件
 35         {
 36             vis[i]=1;
 37             for(int j = 0 ; j < 26 ; j++)
 38                 if(g[i][j]) in[j]--;
 39             char ch = i+‘A‘;
 40             dfs(cnt+1,s+ch);//因为找所有解所以后面要还原之前操作
 41             for(int j = 0 ; j < 26 ;j++)
 42                 if(g[i][j]) in[j]++;
 43             vis[i]=0;
 44         }
 45     }
 46 }
 47
 48 void tuop()//拓扑排序
 49 {
 50      total = 0;
 51     for(int i = 0 ;i < 26 ; i++)
 52         vis[i] = 0,in[i] = 0;
 53     for(int i = 0 ; i < 26 ;i++)
 54         for(int j = 0 ;j < 26 ;j++)
 55             if(g[i][j]) in[j]++;
 56     for(int i = 0 ;i < 26 ;i++)
 57         total +=node[i].flag;
 58     dfs(0,"");
 59 }
 60 int main()
 61 {
 62     while(~scanf("%d%d",&n,&m))
 63     {
 64         for(int i = 0 ;i < n ; i++)
 65             scanf("%s",mp[i]);//如果挨个读入字符两重循环scanf会读入末尾的空行
 66         for(int i =0 ; i < 26; i++)
 67             node[i].init();
 68         for(int i =0 ;i < n ;i++)
 69         {
 70             for(int j = 0 ; j < m ;j++)
 71             {
 72                 if(mp[i][j]==‘.‘) continue;
 73                 int id = mp[i][j]-‘A‘;
 74                 node[id].flag=1;
 75                 node[id].x1 = min(node[id].x1,i);
 76                 node[id].y1 = min(node[id].y1,j);
 77                 node[id].x2 = max(node[id].x2,i);
 78                 node[id].y2 = max(node[id].y2,j);
 79             }
 80         }//找到每个字母对应的照片的位置
 81         memset(g,0,sizeof(g));
 82         for(int i = 0 ;i < 26 ;i++)
 83         {
 84             if(node[i].flag == 0) continue;
 85             int y1 = node[i].y1 , y2 = node[i].y2,x;
 86             for(x = node[i].x1;x<=node[i].x2 ;x++)
 87             {
 88                 if(mp[x][y1]!=i+‘A‘) add(i,mp[x][y1]-‘A‘);
 89                 if(mp[x][y2]!=i+‘A‘) add(i,mp[x][y2]-‘A‘);
 90             }
 91             int x1 = node[i].x1 , x2 = node[i].x2,y;
 92             for(y = node[i].y1;y<=node[i].y2 ;y++)
 93             {
 94                 if(mp[x1][y]!=i+‘A‘) add(i,mp[x1][y]-‘A‘);
 95                 if(mp[x2][y]!=i+‘A‘) add(i,mp[x2][y]-‘A‘);
 96             }
 97         }//扫描每条边并建图,如图这条边上本来应该出现同一个字母的时候出现了其他的就说明了其他的字母在这个字母的照片的上面所以建一条从下面字母到上面字母的有向边
 98         tuop();
 99     }
100     return 0;
101 }
 
时间: 2024-11-10 00:16:41

Frame Stacking(拓扑排序)的相关文章

POJ 1128 &amp; ZOJ 1083 Frame Stacking (拓扑排序)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=83 http://poj.org/problem?id=1128 Frame Stacking Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4102   Accepted: 1378 Description Consider the following 5 picture frames placed

UVA 124 &amp; POJ 1270 Following Orders(拓扑排序)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=60 http://poj.org/problem?id=1270 Following Orders Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3806   Accepted: 1507 Description Or

POJ1128 Frame Stacking(拓扑排序)经典

Frame Stacking Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4454   Accepted: 1509 Description Consider the following 5 picture frames placed on an 9 x 8 array. ........ ........ ........ ........ .CCC.... EEEEEE.. ........ ........ ..

POJ1128 Frame Stacking 【拓扑排序】+【深搜】

Frame Stacking Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4074   Accepted: 1371 Description Consider the following 5 picture frames placed on an 9 x 8 array. ........ ........ ........ ........ .CCC.... EEEEEE.. ........ ........ ..

POJ 1128 Frame Stacking(拓扑排序&amp;#183;打印字典序)

题意  给你一些矩形框堆叠后的鸟瞰图  推断这些矩形框的堆叠顺序  每一个矩形框满足每边都至少有一个点可见  输入保证至少有一个解 按字典序输出全部可行解 和上一题有点像  仅仅是这个要打印全部的可行方案  建图还是类似  由于每一个矩形框的四边都有点可见  所以每一个矩形框的左上角和右下角的坐标是能够确定的  然后一个矩形框上有其他字符时  就让这个矩形框相应的字符和那个其他字符建立一个小于关系  由于要打印方案  所以在有多个入度为0的点时须要用DFS对每种选择都进行一遍拓扑排序 #incl

POJ 1128 Frame Stacking(拓扑排序&#183;打印字典序)

题意  给你一些矩形框堆叠后的俯视图  判断这些矩形框的堆叠顺序  每个矩形框满足每边都至少有一个点可见  输入保证至少有一个解 按字典序输出所有可行解 和上一题有点像  只是这个要打印所有的可行方案  建图还是类似  因为每个矩形框的四边都有点可见  所以每个矩形框的左上角和右下角的坐标是可以确定的  然后一个矩形框上有其它字符时  就让这个矩形框对应的字符和那个其它字符建立一个小于关系  由于要打印方案  所以在有多个入度为0的点时需要用DFS对每种选择都进行一遍拓扑排序 #include

POJ--1128--Frame Stacking【拓扑排序】

链接:http://poj.org/problem?id=1128 题意:有几张图片,给你叠加到一起之后的图,问叠加的可能性,如有多种可能则按字典序由小到大输出. 思路:根据给出的图形建一个图,被覆盖的图片向覆盖它的图片建边,然后拓扑排序. 拓扑排序按照字母顺序从小到大找入度为0的点,用dfs形式的拓扑排序,就按照字典序输出了. POJ1270的做法也类似: 代码 #include<cstring> #include<string> #include<fstream>

USACO Frame Up 矩阵覆盖 拓扑排序

矩阵覆盖的题, 可以转化为拓扑排序.写这个拓扑排序废了好大的劲以后好好看看.代码如下: /* ID: m1500293 LANG: C++ PROG: frameup */ #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int h, w; int x1[30], y1[30], x2[30], y2[30]; int ex[30]; //有没有出现 char

ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083))

经典的拓扑排序问题,难点在于字典序输出和建立拓扑图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacking 题意:每个图片由同一字母组成的边框表示,每个图片的字母都不同: 在一个最多30*30的区域放置这些图片,问底层向顶层叠加的图片次序,多选时按字典序输出 注:每个图片的四边都会有字符显示,其中顶点显示两边. 题解:题意的理解是难点,题目对图片的范围确定说得有点含糊不清,博主一开始就被出现的五张图片的样例迷惑,理解重心放错了.题目最需要理解的是