Southern African 2001 框架折叠 (拓扑序列的应用)
本文链接: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 有一条有向边,根据实际情况建立起来的图就是一个有向无环图,所以这个图上所有的拓扑序列就是答案。
代码:
- #include <stdio.h>
- #include <string.h>
- #include <iostream>
- #include <queue>
- #include <stack>
- #include <algorithm>
- using namespace std;
- const int MAXN = ; //最多26个字母
- char Gra[MAXN][MAXN];//存储初始图
- int head[MAXN + ];//用链式前向星存建立起来的图中
- int flag[MAXN + ][MAXN + ];//flag[i][j]用于判断i 和 j 之间是否有边,用于忽略掉重复边
- int h, w;//高h , 宽 w
- int N; //图中一共有 N 个点
- int e; //图中一共有 e 条边
- struct Map{ //把初始图先转为u v 之间存在的边,再转为链式前向星
- int u;
- int v;
- }map[MAXN * MAXN + ];
- typedef struct EdgeNode{//链式前向星
- int to;
- int next;
- }edgeNode;
- edgeNode Edges[MAXN * MAXN + ];
- typedef struct Point{//坐标
- int x;
- int y;
- }point;
- typedef struct Photo{//照片的位置
- point leftUp;//左上角
- point rightDown;//右下角
- }photos;
- photos pht[MAXN + ];
- int getN()//由初始图获得节点的个数
- {
- int has[] ={};
- for(int i = ; i <= h; i++)
- for(int j = ; j <= w; j++)
- if(Gra[i][j] != '.')
- has[ Gra[i][j] - 'A' ]++;
- int n = ;
- for(int i = ; i <= ; i++)
- if(has[i] != )
- n++;
- return n;
- }
- void getXY()//由初始图获得每个照片的两个对角坐标
- {
- for(int i = ; i <= h; i++)
- {
- for(int j = ; j <= w; j++)
- {
- for(int k = ; k <= N; k++)
- {
- if(Gra[i][j] != '.' && Gra[i][j] == k + 'A' - )
- {
- //cout << "*" << i << " " << j <<"*"<<endl;
- pht[k].leftUp.x = min( pht[k].leftUp.x, i);
- pht[k].leftUp.y = min( pht[k].leftUp.y, j);
- pht[k].rightDown.x = max( pht[k].rightDown.x, i);
- pht[k].rightDown.y = max( pht[k].rightDown.y, j);
- }
- }
- }
- }
- }
- void initPht()//初始化对角坐标
- {
- for(int i = ; i <= N; i++)
- {
- pht[i].leftUp.x = h + ;
- pht[i].leftUp.y = w + ;
- pht[i].rightDown.x = -;
- pht[i].rightDown.y = -;
- }
- }
- void buidEdge(photos pht, int m)//由初始图建立起来的一个基本图
- {
- int go;
- go = pht.leftUp.y;
- //cout << pht.leftUp.x << " " << pht.leftUp.y<<" " << pht.rightDown.x <<" "<< pht.rightDown.y<<endl;
- while( go <= pht.rightDown.y)//横向遍历
- {
- //如果不是'.',且不是本身,且之前尚未有边那么就建立起此边
- if( Gra[pht.leftUp.x][go] != '.' && Gra[pht.leftUp.x][go] != m + 'A' - && flag[Gra[pht.leftUp.x][go] - 'A' + ][m] != )
- {
- //cout << pht.leftUp.x << " ^ " << go << endl;
- ++e;
- flag[Gra[pht.leftUp.x][go] - 'A' + ][m] = ;
- map[e].v = Gra[pht.leftUp.x][go] - 'A' + ;
- map[e].u = m;
- }
- if( Gra[pht.rightDown.x][go] != '.' && Gra[pht.rightDown.x][go] != m + 'A' - && flag[Gra[ pht.rightDown.x][go] - 'A' + ][m] != )
- {
- ++e;
- flag[Gra[ pht.rightDown.x][go] - 'A' + ][m] = ;
- map[e].v = Gra[pht.rightDown.x][go] - 'A' + ;
- map[e].u = m;
- }
- go++;
- }
- go = pht.leftUp.x;
- while( go <= pht.rightDown.x)//纵向遍历
- {
- if( Gra[go][pht.rightDown.y] != '.' && Gra[go][pht.rightDown.y] != m + 'A' - && flag[Gra[go][pht.rightDown.y] - 'A' + ][m] != )
- {
- ++e;
- flag[Gra[go][pht.rightDown.y] - 'A' + ][m] = ;
- map[e].v = Gra[go][pht.rightDown.y] - 'A' + ;
- map[e].u = m;
- }
- if( Gra[go][pht.leftUp.y] != '.' && Gra[go][pht.leftUp.y] != m + 'A' - && flag[Gra[go][pht.leftUp.y] - 'A' + ][m] != )
- {
- ++e;
- flag[Gra[go][pht.leftUp.y] - 'A' + ][m] = ;
- map[e].v = Gra[go][pht.leftUp.y] - 'A' + ;
- map[e].u = m;
- }
- go++;
- }
- }
- int vis[MAXN + ];
- int indegree[MAXN + ];
- void getIdg(int vis[])//获得每个点的入度
- {
- memset(indegree, , sizeof(indegree));
- for(int i = ;i <= N; i++)
- {
- if(!vis[i])
- {
- for(int j = head[i]; j != -; j = Edges[j].next)
- {
- indegree[Edges[j].to ] ++;
- }
- }
- }
- }
- int allVis()//每个点都被删了
- {
- for(int i = ; i <= N; i++)
- if(!vis[i])return ;
- return ;
- }
- void DFS(int head[], int vis[], queue<int> Qu)
- {
- queue<int> q;
- getIdg(vis);
- for(int i = ; i <= N; i++) //每次把入度为 0 的点入到队列中
- if(!vis[i] && !indegree[i]) q.push(i);
- while(!q.empty())
- {
- int v = q.front();
- q.pop();
- queue<int> cpyQu(Qu);//复制Qu的副本并把 点 v 加入到Qu的副本中
- cpyQu.push(v);
- vis[v] = ; //删除已被访问到的点
- int t = head[v];
- head[v] = ; //删除从这个点出发的全部有向边
- if(allVis()) //如果图为空
- {
- while(!cpyQu.empty())
- {
- cout <<(char) (cpyQu.front() + 'A' - ) ;
- cpyQu.pop();
- }
- cout << endl;
- }
- else//继续递归剩下的图,
- DFS(head, vis, cpyQu);
- vis[v] = ;//恢复现场
- head[v] = t;
- }
- }
- int main()
- {
- freopen("in.txt", "r", stdin);
- //freopen("out.txt", "w", stdout);
- while(~scanf("%d%d", &h, &w) && (h || w))
- {
- memset(Gra, , sizeof(Gra));
- for(int i = ; i <= h; i++)
- scanf("%s",Gra[i] + );
- N = getN();//获得N
- initPht();//初始化图片对角的位置
- getXY();//获得图片对角的位置
- e = ;
- memset(flag, , sizeof(flag));
- for(int i = ; i <= N; i++)//建立基本图
- buidEdge(pht[i], i);
- memset(head, -, sizeof(head));
- memset(&Edges, , sizeof(EdgeNode));
- memset(&pht, , sizeof(Photo));
- for(int i = ; i <= e; i++)//根据基本图建立链式前向星的存图结构
- {
- Edges[i].to = map[i].v;
- Edges[i].next = head[map[i].u];
- head[map[i].u] = i;
- }
- memset(vis, , sizeof(vis));
- queue<int> qu;
- DFS(head, vis, qu);//head 用于删除图的边,vis删除边,qu是每次的拓扑序列
- }
- return ;
- }
提供一组测试数据:
/*
AAA*EEEE
ACCCECCE
ACA*E*CE
*C*DEEEE
*C*DD*C*
*C**BBCB
FFF*B*CB
FCFCCCCB
FFF*BBBB
*/

Southern African 2001 框架折叠 (拓扑序列的应用)的更多相关文章
- Southern African 2001 Stockbroker Grapevine /// Floyd oj1345
题目大意: 输入n 接下来n行 每行输入m 接下来m对a,b 若干个人之间会传播谣言,但每个人传播给其他人的速度都不一样, 问最快的传播路线(即耗时最短的)中最耗时的一个传播环节. 如果其中有人不在这 ...
- 图结构练习——判断给定图是否存在合法拓扑序列(dfs算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))
sdut 2140 图结构练习——判断给定图是否存在合法拓扑序列 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 给定一个有向图 ...
- SDUT OJ 数据结构实验之图论十:判断给定图是否存在合法拓扑序列
数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Prob ...
- SDUT2140图结构练习——判断给定图是否存在合法拓扑序列
拓扑序列的判断方法为不存在有向环,代码实现的话有两种,一种是直接去判断是否存在环,较为难理解一些,另一种的话去判断结点入度,如果存在的入度为0的点大于一个,则该有向图肯定不存在一个确定的拓扑序列 #i ...
- acwing 848 有向图的拓扑序列
地址 https://www.acwing.com/problem/content/description/850/ 题目描述给定一个n个点m条边的有向图,图中可能存在重边和自环. 请输出任意一个该有 ...
- SDUT-2140_判断给定图是否存在合法拓扑序列
数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个有向图,判 ...
- UVALive 6467 Strahler Order(拓扑序列)
In geology, a river system can be represented as a directed graph. Each river segment is an edge; wi ...
- Comparing Your Heros拓扑序列的数量
给出N行英雄的比较,每一行包含两个英雄的名字,代表第一个英雄比第二个英雄更受欢迎. 英雄的数目不超过16个.问有多少种可能的受欢迎程度的序列满足N行英雄的比较. 由于只有英雄数目不超过16个,可以用二 ...
- spring,springmvc,mybatis整合ssm框架出现ORA-02289:序列不存在问题
今天整合了一个SSM项目,完了后部署到Tomcat服务器,正常启动.但是当我发送请求时,报错,,如下 报错说序列不存在,可是我明明创建了序列呀,然后我测试了一下,测试语句:select tb_user ...
随机推荐
- ubuntu下eclipse 安装记录
基本是参考:http://www.metsky.com/archives/611.html 完成. 中间遇到小问题,在此记录下,方便遇到同样问题的难友. 先说下快速打开命令行快捷键:Ctrl+Alt+ ...
- unity值得推荐的网址
免费字体下载网站:http://www.dafont.com/ 免费声音文件下载网站:http://freesound.org/ http://incompetech.com/mus ...
- ES6常用片段
promise: --在return里面: methods:{ getSellData(){ return axios.get('/api/seller').then((res=>{ retur ...
- 孤荷凌寒自学python第四十七天通用跨数据库同一数据库中复制数据表函数
孤荷凌寒自学python第四十七天通用跨数据库同一数据库中复制数据表函数 (完整学习过程屏幕记录视频地址在文末) 今天继续建构自感觉用起来顺手些的自定义模块和类的代码. 今天打算完成的是通用的(至少目 ...
- 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘
孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...
- Python——数据类型之list、tuple
本篇主要内容 • list初识 • list元素的访问 • list内部所有的方法 • tuple介绍和与list用法的比较 我觉得Python里面用的最多的就是List了,感觉好强大.他能存 ...
- ExtJs学习之MessAgeBox的使用
1.Ext.MessageBox.alert() 调用格式: alert( String title, String msg, [Function fn], [Object scope] ) 参数说明 ...
- iPhone新建项目不能全屏
上个周做项目的时候,发现新建了一个项目不能全屏.伤透了我的脑筋,然后又请教了团队里其他两个大牛帮我搞定了这个问题. 虽然是搞定了,但也看的出大牛也是云里雾里.歪打正着解决的. 今天又想新做个项目,这个 ...
- [洛谷P4630][APIO2018] Duathlon 铁人两项
题目大意:给一张无向图,求三元组$(u,v,w)$满足$u->v->w$为简单路径,求个数 题解:圆方树,缩点后$DP$,因为同一个点双中的点一定地位相同 卡点:1.$father$数组开 ...
- BZOJ - 2728 与非
题意: 给定N个数,一个数k和一个范围[L,R].每个数可以使用任意次,k表示与非不超过k位.求出范围内有多少个数可以由他们的与非和表示. 题解: m个数进行NAND,最终的数二进制下某一位如果为1, ...