zoukankan      html  css  js  c++  java
  • ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083)-POJ1270)

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


    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] = '';
     36         printf("%s
    ", 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 }

    POJ1270-Following Orders

      本题相当于POJ1128的同类改编题型,相比1128简单。

      题意:给定第一行的小写字母,第二行每两个字母描述其约束关系,例如x y 即 x<y,求可以得到的所有有序序列。

      题解:这个题目的Input也是让人很醉啊,为了循环接受一行字符,需要使用读取到' '才停止的函数。

         可以实现的类似的函数有gets,fgets,sscanf;getchar(循环接受单字符);string的getline和cin的getline及get等等

         为了方便书写和之后的字符处理,折中选取了cin的getline函数

             cin.getline(str,MAX,' '):读入最多MAX大的字符串存入str,直到' '停止(可以不需要第三个参数)

         之后的处理和POJ1128的题解一致,依旧是构图+拓扑排序+DFS,不再累述。

     1 //有序序列-拓扑排序+DFS
     2 //一个难点在于输入,如果使用C语言的gets或者fgets总觉得不好处理
     3 //    于是利用了cin的getline函数,会将'
    '转换成'',利于处理
     4 //另一个难点在于字典序输出,需要利用到DFS的回溯
     5 //其余的操作与拓扑排序相同
     6 //Time:0Ms    Memory:208K
     7 #include<iostream>
     8 #include<cstring>
     9 #include<cstdio>
    10 #include<vector>
    11 #include<algorithm>
    12 using namespace std;
    13 
    14 #define MAX 50
    15 
    16 struct Letter {
    17     vector<int> bigger;
    18     int in;        //in_degree
    19     bool exist;
    20 }let[26];
    21 
    22 int total;
    23 char ans[MAX];
    24 
    25 void dfs(int len)
    26 {
    27     if (len == total)
    28     {
    29         ans[len] = '';
    30         printf("%s
    ", ans);
    31         return;
    32     }
    33 
    34     for (int i = 0; i < 26; i++)
    35     {
    36         if (!let[i].exist || let[i].in) continue;
    37         let[i].in--;
    38         for (unsigned j = 0; j < let[i].bigger.size(); j++)
    39             let[let[i].bigger[j]].in--;
    40         ans[len] = i + 'a';
    41         dfs(len + 1);
    42         for (unsigned j = 0; j < let[i].bigger.size(); j++)
    43             let[let[i].bigger[j]].in++;
    44         let[i].in++;
    45     }
    46 }
    47 
    48 int main()
    49 {
    50     char str[MAX];
    51     while (cin.getline(str, MAX, '
    '))
    52     {
    53         total = 0;
    54         memset(let, 0, sizeof(let));
    55         int len = strlen(str);
    56         for (int i = 0; i < len; i += 2)
    57             if(!let[str[i] - 'a'].exist)
    58                 let[str[i] - 'a'].exist = ++total;
    59 
    60         cin.getline(str, MAX, '
    ');
    61         len = strlen(str);
    62         for (int i = 0; i < len; i += 4)
    63         {
    64             int small = str[i] - 'a';
    65             int big = str[i + 2] - 'a';
    66             let[small].bigger.push_back(big);
    67             let[big].in++;
    68         }
    69 
    70         dfs(0);
    71         printf("
    ");
    72     }
    73     
    74     return 0;
    75 }
    他坐在湖边,望向天空,她坐在对岸,盯着湖面
  • 相关阅读:
    HDOJ/HDU 2560 Buildings(嗯~水题)
    HDOJ/HDU 2555 人人都能参加第30届校田径运动会了(判断加排序~)
    POJ1703Find them, Catch them
    BZOJ2303: [Apio2011]方格染色
    BZOJ2809: [Apio2012]dispatching
    POJ1611The Suspects
    BZOJ2006: [NOI2010]超级钢琴
    BZOJ2288: 【POJ Challenge】生日礼物
    BZOJ1150: [CTSC2007]数据备份Backup
    洛谷P1316 P1824
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5351764.html
Copyright © 2011-2022 走看看