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

经典的拓扑排序问题,难点在于字典序输出和建立拓扑图,另外理解题意是最难的难点,没有之一...



POJ1128(ZOJ1083)-Frame Stacking

  题意:每个图片由同一字母组成的边框表示,每个图片的字母都不同;

     在一个最多30*30的区域放置这些图片,问底层向顶层叠加的图片次序,多选时按字典序输出

     注:每个图片的四边都会有字符显示,其中顶点显示两边。

  题解:题意的理解是难点,题目对图片的范围确定说得有点含糊不清,博主一开始就被出现的五张图片的样例迷惑,理解重心放错了。题目最需要理解的是下方的三句话。

     第一句和数据范围就确定了图片尺寸

     第二句话提示读者应该考虑记录对角线上的两个顶点,以此记录该图片的位置和尺寸

     第三句话确定了图片的数量及可以标明该图片的key值(字母)

     最后要注意Input中有多组样例,而Ouput中的多组次序需要按照字典序输出

     理清题意后:接下来的工作就是先用两个顶点确立图片的位置和尺寸

           接着利用各图片的位置和尺寸确定覆盖关系建立拓扑图

           最后利用DFS的回溯完成字典序的拓扑排序即可。

  1 //叠图片-拓扑排序+DFS
  2 //每个图片由同一字母组成的边框表示,每个图片的字母都不同
  3 //在一个最多30*30的区域放置这些图片,问底层向顶层叠加的图片次序,多选时按字典序输出
  4 //注:每个图片的四边都至少会有一个字符显示
  5 //Time:0Ms    Memory:180K
  6 #include<iostream>
  7 #include<cstring>
  8 #include<cstdio>
  9 #include<vector>
 10 #include<algorithm>
 11 using namespace std;
 12
 13 #define MAXN 31    //地图长宽
 14 #define MAXL 26    //字母
 15
 16 struct Coordinate{
 17     int x, y;
 18 }lt[MAXL], rb[MAXL];    //left_top - right_bottom
 19
 20 struct Letter {
 21     vector<int> covered;
 22     int in;            //in_degree
 23     bool exist;
 24 }let[MAXL];
 25
 26 int row, col;
 27 int total;    //字母个数
 28 char ans[MAXL+1];
 29 char board[MAXN][MAXN];
 30
 31 void dfs(int len)
 32 {
 33     if (len == total)
 34     {
 35         ans[len] = ‘\0‘;
 36         printf("%s\n", ans);
 37         return;
 38     }
 39
 40     for (int i = 0; i < MAXL; i++)
 41     {
 42         if (!let[i].exist) continue;
 43         if (let[i].in == 0)
 44         {
 45             ans[len] = i + ‘A‘;
 46             let[i].in--;
 47             for (int j = 0; j < let[i].covered.size(); j++)
 48                 let[let[i].covered[j]].in--;
 49             dfs(len + 1);
 50             for (int j = 0; j < let[i].covered.size(); j++)
 51                 let[let[i].covered[j]].in++;
 52             let[i].in++;
 53         }
 54     }
 55
 56 }
 57
 58 int main()
 59 {
 60     while (scanf("%d%d", &row, &col) != EOF)
 61     {
 62         total = 0;
 63         memset(let, 0, sizeof(let));
 64         memset(lt, 0x3f, sizeof(lt));
 65         memset(rb, -1, sizeof(rb));
 66         //Input and Init
 67         for (int i = 0; i < row; i++)
 68         {
 69             scanf("%s", board[i]);
 70             for (int j = 0; j < col; j++)
 71             {
 72                 if (board[i][j] == ‘.‘) continue;
 73                 int t = board[i][j] - ‘A‘;
 74                 if (!let[t].exist)
 75                     let[t].exist = ++total;
 76                 lt[t].x = min(lt[t].x, i);
 77                 lt[t].y = min(lt[t].y, j);
 78                 rb[t].x = max(rb[t].x, i);
 79                 rb[t].y = max(rb[t].y, j);
 80             }
 81         }
 82
 83         //get_Map
 84         for (int k = 0; k < MAXL; k++)
 85         {
 86             if (!let[k].exist) continue;
 87             for (int i = lt[k].x; i <= rb[k].x; i++)
 88                 for (int j = lt[k].y; j <= rb[k].y; j++)
 89                 {
 90                     if (i > lt[k].x && i < rb[k].x && j == lt[k].y + 1)
 91                         j = rb[k].y;
 92                     int cur = board[i][j] - ‘A‘;
 93                     if (cur == k) continue;
 94                     let[k].covered.push_back(cur);
 95                     let[cur].in++;
 96                 }
 97         }
 98
 99         //Topology and Output
100         dfs(0);
101     }
102
103     return 0;
104 }
时间: 2024-10-02 01:07:50

ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083))的相关文章

ACM/ICPC 之 拓扑排序-反向(POJ3687)

难点依旧是题意....需要反向构图+去重+看题 POJ3687-Labeling Balls 题意:1-N编号的球,输出满足给定约束的按原编号排列的重量序列,如果有多组答案,则输出编号最小的Ball重量最轻,若依旧多组则输出编号次小的Ball重量最轻的方案. 题解:在看懂题意后,再开始做会省很多时间...曲解题意还真是人类的本能啊. 为了完成单向关系排序,需要用到拓扑排序: 为了符合编号最小的重量最轻...的题意,需要用到反向拓扑排序: 输入可能会有重复的关系,因此需要判重: 输出需要按原编号输

poj 1270 Following Orders(拓扑排序+dfs)

大致题意:每个样例包含两行,第一行输入n个字符,可能是无序的.第二行输入成对的a b,代表a要在b前面.输出所有的符合这样的序列. 思路:很明显的拓扑排序.要输出所有的序列,那么就从入度为0的点进行dfs,每次选择一个入度为0的点,加入输出序列并把与它相邻的点的入度减一.dfs结束后要把状态再改回来. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include

poj1270Following Orders(拓扑排序+dfs回溯)

题目链接: 啊哈哈,点我点我 题意是: 第一列给出所有的字母数,第二列给出一些先后顺序.然后按字典序最小的方式输出所有的可能性... 思路: 总体来说是拓扑排序,但是又很多细节要考虑,首先要按字典序最小的方式输出,所以自然输入后要对这些字母进行排列,然后就是输入了,用scanf不能读空格,所以怎么建图呢??设置一个变量判断读入的先后顺序,那么建图完毕后,就拓扑排序了,那么多种方式自然就是dfs回溯了..那么这个问题就得到了解决.. 题目: Following Orders Time Limit:

HDU 5438 Ponds (拓扑排序+DFS)2015 ACM/ICPC Asia Regional Changchun Online

[题目链接]:click here~~ [题目大意]: 题意:在一个无向图中有 p 个点, m 条边,每个点有一个值 vi .不断的删去度数小于2的点直到不能删为止.求新图中所有点个数为奇数的连通分量的点值的和. 1<p<10^4,1<m<10^5 [思路]删边考虑类似拓扑排序的写法,不过topsort是循环一遍1到n结点入度为0的结点,然后加入到队列中,这里只要改一下度数小于等于1,最后DFS 判断一下 挫挫的代码: /* * Problem: HDU No.5438 * Run

HDU 5438 拓扑排序+DFS

Ponds Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 3234    Accepted Submission(s): 997 Problem Description Betty owns a lot of ponds, some of them are connected with other ponds by pipes, a

Codeforces Round #292 (Div. 2) D. Drazil and Tiles [拓扑排序 dfs]

传送门 D. Drazil and Tiles time limit per test 2 seconds memory limit per test 256 megabytes Drazil created a following problem about putting 1 × 2 tiles into an n × m grid: "There is a grid with some cells that are empty and some cells that are occupie

拓扑排序/DFS HDOJ 4324 Triangle LOVE

题目传送门 题意:判三角恋(三元环).如果A喜欢B,那么B一定不喜欢A,任意两人一定有关系连接 分析:正解应该是拓扑排序判环,如果有环,一定是三元环,证明. DFS:从任意一点开始搜索,搜索过的点标记,否则超时.看是否存在两点路程只差等于2,如果存在,则说明有上述的三角环.其他做法. 收获:DFS搜索一定要用vis数组啊,否则很容易超时的 代码(拓扑排序): /************************************************ * Author :Running_T

ACM: hihicoder #1174 : 拓扑排序&#183;一 STL- queue

#1174 : 拓扑排序·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 由于今天上课的老师讲的特别无聊,小Hi和小Ho偷偷地聊了起来. 小Ho:小Hi,你这学期有选什么课么? 小Hi:挺多的,比如XXX1,XXX2还有XXX3.本来想选YYY2的,但是好像没有先选过YYY1,不能选YYY2. 小Ho:先修课程真是个麻烦的东西呢. 小Hi:没错呢.好多课程都有先修课程,每次选课之前都得先查查有没有先修.教务公布的先修课程记录都是好多年前的,不但有重复的信息,好像

关于拓扑排序的一些想法

前几天数据结构课上老师给我们留了一道思考题:如何求出拓扑排序的所有可能路径.说实话,自己的第一感觉就是深搜DFS,但是到最后又被自己推翻了,本来周三的时候想到了一个算法,后来又被自己推翻了.在BestCoder群里问了几个大神,他们也没给出什么好的方法,印象深刻的是有人说我问这种题有意义吗,问得我竟然无法反驳,也是,大多数的人总是要为自己的无知做一些辩解. 后来整理了一下自己之前所想的,虽然有很大一个漏洞(这就是我推翻我算法的原因),不过自己所想到的算法自己都用代码实现了,也算是一件成功的事情.