本文链接:http://www.cnblogs.com/Ash-ly/p/5398377.html

题目:
考虑五个图片堆叠在一起,比如下面的9 * 8 的矩阵表示的是这些图片的边缘框。

现在上面的图片顺序为图片1放在最底下,5放在最顶上。如果任何图片的边框覆盖了其他图片的边框,被覆盖的部分不会被显示出来。

下面是一个栗子:

那么从低向上图片的堆叠顺序为 EDABC,现在的问题是给出一个堆叠后的表示,要确定从低向上的图片的堆叠顺序。

下面是判定规则:

1、图片一定是由一个字母表示并且每条边至少三个字符

2、题目保证至少会给出每条边的一个字母,一个角的一个字符代表两条边

3、图片边框用大写字母表示,并且不会有俩张图片的边框使用同一个大写字母

输入:

高度h 、宽度w、接下来是一个h * w 的矩阵,输入数据可能包括多组,中间没有空行

输出:

输出自底向上形成输入状况的图片边框所对应的字母。如果有多组排列方式,将所有的序列按照字母序排列输出。每个可行的序列战一行,对于每个输入确保至少有一个合法的序列满足题意。两组数据之间没有空格。

解题思路:

  首先由于题目中的第二个条件,所以就可以把每个图片的四个角的坐标找到,但是其实只要俩个对角的坐标就可以确定这个图片的位置了,所以只需要找到每个图片的俩个对角的坐标就行了,然后就需要对图再进行一次遍历,如果在应该出现A的地方出现了B那么说明B应该在A的上面,即B覆盖了A。然后就可以把图片边框之间的上下层次关系确定下来,之后就可以利用到拓扑排序了,如果A在B下面,那么我们就认为 Va --> Vb 有一条有向边,根据实际情况建立起来的图就是一个有向无环图,所以这个图上所有的拓扑序列就是答案。

代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <iostream>
  4. #include <queue>
  5. #include <stack>
  6. #include <algorithm>
  7. using namespace std;
  8.  
  9. const int MAXN = ; //最多26个字母
  10. char Gra[MAXN][MAXN];//存储初始图
  11. int head[MAXN + ];//用链式前向星存建立起来的图中
  12. int flag[MAXN + ][MAXN + ];//flag[i][j]用于判断i 和 j 之间是否有边,用于忽略掉重复边
  13. int h, w;//高h , 宽 w
  14. int N; //图中一共有 N 个点
  15. int e; //图中一共有 e 条边
  16.  
  17. struct Map{ //把初始图先转为u v 之间存在的边,再转为链式前向星
  18. int u;
  19. int v;
  20. }map[MAXN * MAXN + ];
  21.  
  22. typedef struct EdgeNode{//链式前向星
  23. int to;
  24. int next;
  25. }edgeNode;
  26. edgeNode Edges[MAXN * MAXN + ];
  27.  
  28. typedef struct Point{//坐标
  29. int x;
  30. int y;
  31. }point;
  32.  
  33. typedef struct Photo{//照片的位置
  34. point leftUp;//左上角
  35. point rightDown;//右下角
  36. }photos;
  37. photos pht[MAXN + ];
  38.  
  39. int getN()//由初始图获得节点的个数
  40. {
  41. int has[] ={};
  42. for(int i = ; i <= h; i++)
  43. for(int j = ; j <= w; j++)
  44. if(Gra[i][j] != '.')
  45. has[ Gra[i][j] - 'A' ]++;
  46. int n = ;
  47. for(int i = ; i <= ; i++)
  48. if(has[i] != )
  49. n++;
  50. return n;
  51. }
  52.  
  53. void getXY()//由初始图获得每个照片的两个对角坐标
  54. {
  55. for(int i = ; i <= h; i++)
  56. {
  57. for(int j = ; j <= w; j++)
  58. {
  59. for(int k = ; k <= N; k++)
  60. {
  61. if(Gra[i][j] != '.' && Gra[i][j] == k + 'A' - )
  62. {
  63. //cout << "*" << i << " " << j <<"*"<<endl;
  64. pht[k].leftUp.x = min( pht[k].leftUp.x, i);
  65. pht[k].leftUp.y = min( pht[k].leftUp.y, j);
  66. pht[k].rightDown.x = max( pht[k].rightDown.x, i);
  67. pht[k].rightDown.y = max( pht[k].rightDown.y, j);
  68. }
  69. }
  70. }
  71. }
  72. }
  73.  
  74. void initPht()//初始化对角坐标
  75. {
  76. for(int i = ; i <= N; i++)
  77. {
  78. pht[i].leftUp.x = h + ;
  79. pht[i].leftUp.y = w + ;
  80. pht[i].rightDown.x = -;
  81. pht[i].rightDown.y = -;
  82. }
  83. }
  84.  
  85. void buidEdge(photos pht, int m)//由初始图建立起来的一个基本图
  86. {
  87. int go;
  88. go = pht.leftUp.y;
  89. //cout << pht.leftUp.x << " " << pht.leftUp.y<<" " << pht.rightDown.x <<" "<< pht.rightDown.y<<endl;
  90. while( go <= pht.rightDown.y)//横向遍历
  91. {
  92. //如果不是'.',且不是本身,且之前尚未有边那么就建立起此边
  93. if( Gra[pht.leftUp.x][go] != '.' && Gra[pht.leftUp.x][go] != m + 'A' - && flag[Gra[pht.leftUp.x][go] - 'A' + ][m] != )
  94. {
  95. //cout << pht.leftUp.x << " ^ " << go << endl;
  96. ++e;
  97. flag[Gra[pht.leftUp.x][go] - 'A' + ][m] = ;
  98. map[e].v = Gra[pht.leftUp.x][go] - 'A' + ;
  99. map[e].u = m;
  100. }
  101. if( Gra[pht.rightDown.x][go] != '.' && Gra[pht.rightDown.x][go] != m + 'A' - && flag[Gra[ pht.rightDown.x][go] - 'A' + ][m] != )
  102. {
  103. ++e;
  104. flag[Gra[ pht.rightDown.x][go] - 'A' + ][m] = ;
  105. map[e].v = Gra[pht.rightDown.x][go] - 'A' + ;
  106. map[e].u = m;
  107. }
  108. go++;
  109. }
  110. go = pht.leftUp.x;
  111. while( go <= pht.rightDown.x)//纵向遍历
  112. {
  113. if( Gra[go][pht.rightDown.y] != '.' && Gra[go][pht.rightDown.y] != m + 'A' - && flag[Gra[go][pht.rightDown.y] - 'A' + ][m] != )
  114. {
  115. ++e;
  116. flag[Gra[go][pht.rightDown.y] - 'A' + ][m] = ;
  117. map[e].v = Gra[go][pht.rightDown.y] - 'A' + ;
  118. map[e].u = m;
  119. }
  120. if( Gra[go][pht.leftUp.y] != '.' && Gra[go][pht.leftUp.y] != m + 'A' - && flag[Gra[go][pht.leftUp.y] - 'A' + ][m] != )
  121. {
  122. ++e;
  123. flag[Gra[go][pht.leftUp.y] - 'A' + ][m] = ;
  124. map[e].v = Gra[go][pht.leftUp.y] - 'A' + ;
  125. map[e].u = m;
  126. }
  127. go++;
  128. }
  129. }
  130.  
  131. int vis[MAXN + ];
  132. int indegree[MAXN + ];
  133.  
  134. void getIdg(int vis[])//获得每个点的入度
  135. {
  136. memset(indegree, , sizeof(indegree));
  137. for(int i = ;i <= N; i++)
  138. {
  139. if(!vis[i])
  140. {
  141. for(int j = head[i]; j != -; j = Edges[j].next)
  142. {
  143. indegree[Edges[j].to ] ++;
  144. }
  145. }
  146. }
  147. }
  148.  
  149. int allVis()//每个点都被删了
  150. {
  151. for(int i = ; i <= N; i++)
  152. if(!vis[i])return ;
  153. return ;
  154. }
  155.  
  156. void DFS(int head[], int vis[], queue<int> Qu)
  157. {
  158. queue<int> q;
  159. getIdg(vis);
  160. for(int i = ; i <= N; i++) //每次把入度为 0 的点入到队列中
  161. if(!vis[i] && !indegree[i]) q.push(i);
  162. while(!q.empty())
  163. {
  164. int v = q.front();
  165. q.pop();
  166. queue<int> cpyQu(Qu);//复制Qu的副本并把 点 v 加入到Qu的副本中
  167. cpyQu.push(v);
  168. vis[v] = ; //删除已被访问到的点
  169. int t = head[v];
  170. head[v] = ; //删除从这个点出发的全部有向边
  171. if(allVis()) //如果图为空
  172. {
  173. while(!cpyQu.empty())
  174. {
  175. cout <<(char) (cpyQu.front() + 'A' - ) ;
  176. cpyQu.pop();
  177. }
  178. cout << endl;
  179. }
  180. else//继续递归剩下的图,
  181. DFS(head, vis, cpyQu);
  182. vis[v] = ;//恢复现场
  183. head[v] = t;
  184. }
  185. }
  186.  
  187. int main()
  188. {
  189. freopen("in.txt", "r", stdin);
  190. //freopen("out.txt", "w", stdout);
  191. while(~scanf("%d%d", &h, &w) && (h || w))
  192. {
  193. memset(Gra, , sizeof(Gra));
  194. for(int i = ; i <= h; i++)
  195. scanf("%s",Gra[i] + );
  196. N = getN();//获得N
  197. initPht();//初始化图片对角的位置
  198. getXY();//获得图片对角的位置
  199. e = ;
  200. memset(flag, , sizeof(flag));
  201. for(int i = ; i <= N; i++)//建立基本图
  202. buidEdge(pht[i], i);
  203. memset(head, -, sizeof(head));
  204. memset(&Edges, , sizeof(EdgeNode));
  205. memset(&pht, , sizeof(Photo));
  206. for(int i = ; i <= e; i++)//根据基本图建立链式前向星的存图结构
  207. {
  208. Edges[i].to = map[i].v;
  209. Edges[i].next = head[map[i].u];
  210. head[map[i].u] = i;
  211. }
  212. memset(vis, , sizeof(vis));
  213. queue<int> qu;
  214. DFS(head, vis, qu);//head 用于删除图的边,vis删除边,qu是每次的拓扑序列
  215. }
  216. return ;
  217. }

提供一组测试数据:

/*
AAA*EEEE
ACCCECCE
ACA*E*CE
*C*DEEEE
*C*DD*C*
*C**BBCB
FFF*B*CB
FCFCCCCB
FFF*BBBB

*/

Southern African 2001 框架折叠 (拓扑序列的应用)的更多相关文章

  1. Southern African 2001 Stockbroker Grapevine /// Floyd oj1345

    题目大意: 输入n 接下来n行 每行输入m 接下来m对a,b 若干个人之间会传播谣言,但每个人传播给其他人的速度都不一样, 问最快的传播路线(即耗时最短的)中最耗时的一个传播环节. 如果其中有人不在这 ...

  2. 图结构练习——判断给定图是否存在合法拓扑序列(dfs算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))

    sdut 2140 图结构练习——判断给定图是否存在合法拓扑序列 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述  给定一个有向图 ...

  3. SDUT OJ 数据结构实验之图论十:判断给定图是否存在合法拓扑序列

    数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Prob ...

  4. SDUT2140图结构练习——判断给定图是否存在合法拓扑序列

    拓扑序列的判断方法为不存在有向环,代码实现的话有两种,一种是直接去判断是否存在环,较为难理解一些,另一种的话去判断结点入度,如果存在的入度为0的点大于一个,则该有向图肯定不存在一个确定的拓扑序列 #i ...

  5. acwing 848 有向图的拓扑序列

    地址 https://www.acwing.com/problem/content/description/850/ 题目描述给定一个n个点m条边的有向图,图中可能存在重边和自环. 请输出任意一个该有 ...

  6. SDUT-2140_判断给定图是否存在合法拓扑序列

    数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个有向图,判 ...

  7. UVALive 6467 Strahler Order(拓扑序列)

    In geology, a river system can be represented as a directed graph. Each river segment is an edge; wi ...

  8. Comparing Your Heros拓扑序列的数量

    给出N行英雄的比较,每一行包含两个英雄的名字,代表第一个英雄比第二个英雄更受欢迎. 英雄的数目不超过16个.问有多少种可能的受欢迎程度的序列满足N行英雄的比较. 由于只有英雄数目不超过16个,可以用二 ...

  9. spring,springmvc,mybatis整合ssm框架出现ORA-02289:序列不存在问题

    今天整合了一个SSM项目,完了后部署到Tomcat服务器,正常启动.但是当我发送请求时,报错,,如下 报错说序列不存在,可是我明明创建了序列呀,然后我测试了一下,测试语句:select tb_user ...

随机推荐

  1. ubuntu下eclipse 安装记录

    基本是参考:http://www.metsky.com/archives/611.html 完成. 中间遇到小问题,在此记录下,方便遇到同样问题的难友. 先说下快速打开命令行快捷键:Ctrl+Alt+ ...

  2. unity值得推荐的网址

    免费字体下载网站:http://www.dafont.com/ 免费声音文件下载网站:http://freesound.org/          http://incompetech.com/mus ...

  3. ES6常用片段

    promise: --在return里面: methods:{ getSellData(){ return axios.get('/api/seller').then((res=>{ retur ...

  4. 孤荷凌寒自学python第四十七天通用跨数据库同一数据库中复制数据表函数

    孤荷凌寒自学python第四十七天通用跨数据库同一数据库中复制数据表函数 (完整学习过程屏幕记录视频地址在文末) 今天继续建构自感觉用起来顺手些的自定义模块和类的代码. 今天打算完成的是通用的(至少目 ...

  5. 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘

    孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...

  6. Python——数据类型之list、tuple

    本篇主要内容 •  list初识 •  list元素的访问 •  list内部所有的方法 •  tuple介绍和与list用法的比较 我觉得Python里面用的最多的就是List了,感觉好强大.他能存 ...

  7. ExtJs学习之MessAgeBox的使用

    1.Ext.MessageBox.alert() 调用格式: alert( String title, String msg, [Function fn], [Object scope] ) 参数说明 ...

  8. iPhone新建项目不能全屏

    上个周做项目的时候,发现新建了一个项目不能全屏.伤透了我的脑筋,然后又请教了团队里其他两个大牛帮我搞定了这个问题. 虽然是搞定了,但也看的出大牛也是云里雾里.歪打正着解决的. 今天又想新做个项目,这个 ...

  9. [洛谷P4630][APIO2018] Duathlon 铁人两项

    题目大意:给一张无向图,求三元组$(u,v,w)$满足$u->v->w$为简单路径,求个数 题解:圆方树,缩点后$DP$,因为同一个点双中的点一定地位相同 卡点:1.$father$数组开 ...

  10. BZOJ - 2728 与非

    题意: 给定N个数,一个数k和一个范围[L,R].每个数可以使用任意次,k表示与非不超过k位.求出范围内有多少个数可以由他们的与非和表示. 题解: m个数进行NAND,最终的数二进制下某一位如果为1, ...