题目链接:http://poj.org/problem?id=1128

题意:给你一个平面,里面有些矩形(由字母围成),这些矩形互相有覆盖关系,请从求出最底层的矩形到最上层的矩形的序列,如果存在多种序列,答案按照字典序依次输出。

思路:这道题的难点在建图,利用矩形之间的覆盖关系建图,说着容易,实际上仔细想想不太容易。由于矩形的任意一个边界不会完全被覆盖,所以我们可以确定一个矩形的上下左右边界,然后对每个矩形的上下左右边界扫一遍,看是否被其他字母所覆盖,利用覆盖关系建图。这里无法利用队列的方式拓扑排序,因为要输出所有的序列,所以dfs的方式更为出色,具体的注释都写在代码里面了。

//Author: xiaowuga
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <map>
#include <bitset>
#include <cctype>
#define maxx INT_MAX
#define minn INT_MIN
#define inf 0x3f3f3f3f
#define mem(s,ch) memset(s,ch,sizeof(s))
#define da cout<<"da"<<endl
#define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
#define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
const long long N=;
using namespace std;
typedef long long LL;
int L[N],R[N],U[N],D[N],in[N],vis[N],v[N];
//L左边界数组,R有边界数组,U上边界数组,D下边界数组
//vis字母存在数组,v是dfs中是否访问数组
char pic[N][N],ans[N];
int p[N][N];
int n,m,ct;
//初始化
void init(){
ct=;//存在字母总数量初始化为0
mem(in,);//入度数组初始化为0
mem(vis,);//字母存在数组初始化为0
mem(v,);
mem(p,);//邻接矩阵初始化为0
//上左边界最大化,下右边界最小化
mem(L,inf);mem(U,inf);mem(R,-);mem(D,-);
}
void make_g(int i,int j,int k){
int t=pic[i][j]-'A';
if(k!=t){
if(!p[k][t]) {p[k][t]=;in[t]++;}
}
}
void dfs(int x,int y){
ans[y]=x+'A';
v[x]=;//标记为访问过
if(y==ct){//全部字母已经排好拓扑序
for(int i=;i<=ct;i++) cout<<ans[i];cout<<endl;//输出
v[x]=;//恢复
return ;
}
int q[N],num=;
//i从0-26保证了字典序
for(int i=;i<;i++){
if(p[x][i]) --in[i];//存在连接则连接减少入度
if(vis[i]&&!in[i]&&!v[i]) q[num++]=i;//存在连接且入度减为0,且未访问
}
//对所有后续节点进行dfs
for(int i=;i<num;++i) dfs(q[i],y+);
for(int i=;i<;i++) if(p[x][i]) in[i]++;//恢复
v[x]=;//恢复
}
void topo(){
for(int i=;i<;++i) if(vis[i]&&!in[i]) dfs(i,);
}
int main() {
ios::sync_with_stdio(false);cin.tie();
while(cin>>n>>m){
init();
//输入整个图形并确定每个矩形的上下左右边界
for(int i=;i<n;++i) for(int j=;j<m;++j){
cin>>pic[i][j];
if(pic[i][j]!='.'){
int t=pic[i][j]-'A';
if(!vis[t]){ vis[t]=;ct++;}
L[t]=min(L[t],j);
R[t]=max(R[t],j);
U[t]=min(U[t],i);
D[t]=max(D[t],i);
}
}
for(int k=;k<;k++){
if(vis[k]){
int i,j;
i=U[k];//上边界上
for(j=L[k];j<=R[k];j++) make_g(i,j,k);
i=D[k];//下边界上
for(j=L[k];j<=R[k];j++) make_g(i,j,k);
j=L[k];//左边界上
for(i=U[k]+;i<D[k];i++) make_g(i,j,k);
j=R[k];//右边界上
for(i=U[k]+;i<D[k];i++) make_g(i,j,k);
}
}
topo();
}
return ;
}

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

  1. POJ 1128 Frame Stacking (拓扑排序)

    题目链接 Description Consider the following 5 picture frames placed on an 9 x 8 array. ........ ........ ...

  2. Frame Stacking 拓扑排序 图论

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

  3. POJ 1128 Frame Stacking 拓扑排序+暴搜

    这道题输出特别坑.... 题目的意思也不太好理解.. 就解释一下输出吧.. 它让你 从下往上输出. 如果有多种情况,按照字典序从小往大输出... 就是这个多种情况是怎么产生的呢. 下面给一组样例. 很 ...

  4. POJ1128 Frame Stacking(拓扑排序+dfs)题解

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

  5. 图论之拓扑排序 poj1128 Frame Stacking

    题目网址 http://poj.org/problem?id=1128 思路:遍历找出每一种字母出现的最大和最小的横纵坐标,假如本应出现字母A的地方出现了字母B,那么A一定在字母B之前,这就相当于点A ...

  6. Frame Stacking(拓扑排序)

    题目链接:http://acm.tju.edu.cn/toj/showp1076.html1076.   Frame Stacking Time Limit: 1.0 Seconds   Memory ...

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

    题意  给你一些矩形框堆叠后的鸟瞰图  推断这些矩形框的堆叠顺序  每一个矩形框满足每边都至少有一个点可见  输入保证至少有一个解 按字典序输出全部可行解 和上一题有点像  仅仅是这个要打印全部的可行 ...

  8. ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083)-POJ1270)

    两道经典的同类型拓扑排序+DFS问题,第二题较第一题简单,其中的难点在于字典序输出+建立单向无环图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacki ...

  9. USACO4.4 Frame Up【拓扑排序】

    题意居然还读了好久... 读完题目之后大概就知道拓扑排序了.用拓扑可以求出一些字母之间的关系,谁先,谁后.但是这个关系不是唯一确定的,所以就会产生多种方案(题目还要求按字典序输出所有的方案) 输出方案 ...

随机推荐

  1. CCOrbitCamera

    Cocos2d-x提供了一中根据球面坐标轨迹旋转的方式CCOrbitCamera CC_DEPRECATED_ATTRIBUTE static CCOrbitCamera* actionWithDur ...

  2. linux中录屏工具byzanz

    linux中录屏工具byzanz: 1.安装 sudo apt install byzanz 2.使用 help:byzanz-record --help 配合xwininfo使用--xwininfo ...

  3. Mac下Selenium无法最大化Chrome解决方案

    在用Selenium做自动化操作时,一般最大化浏览器的代码都是:driver.manage().window().maximize(), 但是在Mac下这样是无法最大化Chrome浏览器的,解决方法: ...

  4. JAVA-Word转PDF各种版本实现方式

    当下做一个项目,就是各种操作office,客户的需求总是各种不按常理,来需求就得搞啊.对JAVA操作office这方面真是头大,弟弟是真滴不懂不会啊.无奈只好试啊试的.网上一大堆好使的,一大堆不好使的 ...

  5. django 判断用户是否登陆

    基于类的视图登陆

  6. Python 内置模块函数filter reduce

    1.filter()实现过滤的功能 2.reduce()对序列中元素的连续操作可以通过循环来处理 3.map()对tuple元组进行解包操作,调用时设置map()的第一个参数为None 4.使用red ...

  7. python学习笔记(9)--Python UnicodeEncodeError: 'gbk' codec can't encode character 解决方法

    Python UnicodeEncodeError: 'gbk' codec can't encode character 解决方法 这篇文章主要介绍了Python UnicodeEncodeErro ...

  8. alsamixer 在音频子系统的使用

    alsamixer是Linux 音频架构ALSA工具的其中一个,用于配置音频的各个参数. alsamixer是基于文本下的图形界面的,可以通过键盘的上下键,左右键等,很方便地设置需要的音量,开关某个s ...

  9. Android基础总结(六)Activity

    创建第二个Activity(掌握) 需要在清单文件中为其配置一个activity标签 标签中如果带有这个子节点,则会在系统中多创建一个快捷图标 <intent-filter> <ac ...

  10. selenium使用中遇到的问题

    1.Exception in thread "main" org.openqa.selenium.WebDriverException: Cannot find firefox b ...