zoukankan      html  css  js  c++  java
  • USACO 4.4 Frame up Topological Sort

    题目描述

    看下面的五张 9 x 8 的图像:

    ........   ........   ........   ........   .CCC....
    EEEEEE..   ........   ........   ..BBBB..   .C.C....
    E....E..   DDDDDD..   ........   ..B..B..   .C.C....
    E....E..   D....D..   ........   ..B..B..   .CCC....
    E....E..   D....D..   ....AAAA   ..B..B..   ........
    E....E..   D....D..   ....A..A   ..BBBB..   ........
    E....E..   DDDDDD..   ....A..A   ........   ........
    E....E..   ........   ....AAAA   ........   ........
    EEEEEE..   ........   ........   ........   ........
    
       1          2           3          4          5

    现在,把这些图像按照 1—5 的编号从下到上重叠,第 1 张在最下面,第 5 张在最顶端。如果一张图像覆盖了另外一张图像,那么底下的图像的一部分就变得不可见了。我们得到下面的图像:

                 .CCC....
                 ECBCBB..
                 DCBCDB..
                 DCCC.B..
                 D.B.ABAA
                 D.BBBB.A
                 DDDDAD.A
                 E...AAAA
                 EEEEEE..

    对于这样一张图像,计算构成这张图像的矩形图像从底部到顶端堆叠的顺序。

    下面是这道题目的规则:

    矩形的边的宽度为 1 ,每条边的长度都不小于 3 。

    矩形的每条边中,至少有一部分是可见的。注意,一个角同时属于两条边。

    矩形用大写字母表示,并且每个矩形的表示符号都不相同。

    输入输出格式

    输入格式:

    第一行 两个用空格分开的整数:图像高 H (3 <= H <=30) 和图像宽 W (3 <= W <= 30) 。

    第二行到第 H+1 行 H 行,每行 W 个字母。

    输出格式:

    按照自底向上的顺序输出字母。如果有不止一种情况,按照字典顺序输出每一种情况(至少会有一种合法的顺序)。

    输入输出样例

    输入样例#1: 
    9 8
    .CCC....
    ECBCBB..
    DCBCDB..
    DCCC.B..
    D.B.ABAA
    D.BBBB.A
    DDDDAD.A
    E...AAAA
    EEEEEE..
    输出样例#1:
    EDABC

    说明

    题目翻译来自NOCOW。

    USACO Training Section 4.4

    分析

    因为每条边上都至少给出一个点,所以很容易算出四边形的所在位置和大小(其实就是四边形在四个方向上的最远坐标)。

    然后进行判断谁一定在谁的上方,方法是:在每个矩形的边上,若出现了另一个矩形的符号,那么这个出现的矩形就在这个矩形的上方。然后建立一条有向边,从上方的矩形指向下方的矩形。建立边的同时累加矩形的入度(D[])。

    最后进行拓扑排序,这里是DFS的版本。

    注意几个地方:

    1. 60~63行的地方,在两个方向上,哪个是i,哪个是j要分清楚。例如:在横向上,i是固定的,要更新的是j。
    2. 输出注意并没有空格。
    3. 提交OJ不要加文件,查了一个小时居然是这种错误QAQ。OJ上显示是"Too many or too few lines."以至于我还认为是只输出了一种情况。结果最后发现居然提交了带文件的程序。

    程序

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int MAXL = 30 + 1;
     4 const int INF = 0x3F3F3F3F;
     5 struct node
     6 {
     7     int Left, Right, Top, Bottom;
     8 }spots[27];
     9 bool flag[27][27], v[27];
    10 int H, W, Head[27], p[27], CountP, D[27];
    11 char frame[MAXL][MAXL];
    12 // Topological Sort based on DFS
    13 void dfs()
    14 {
    15     bool f = 0;
    16     for (int i = 1; i <= 26; i++)
    17         if(v[i])
    18         {
    19             f = 1;
    20             break;
    21         }
    22     if(!f)
    23     {
    24         for (int i = 1; i <= CountP; i++)
    25         {
    26                 cout << (char)p[i];
    27         }
    28         cout << endl; 
    29         return;
    30     }
    31     for (int i = 1; i <= 26; i++)
    32         if(v[i] && D[i] == 0)
    33         {
    34             p[++CountP] = i + '@';
    35             for (int j = 1; j <= 26; j++)
    36                 if(flag[i][j])
    37                     D[j]--;
    38             v[i] = 0;
    39             dfs();
    40             for (int j = 1; j <= 26; j++)
    41                 if(flag[i][j])
    42                     D[j]++;
    43             v[i] = 1;
    44             CountP--;
    45         }
    46 }
    47 int main()
    48 {
    49     for (int i = 1; i <= 26; i++)
    50         spots[i].Left = INF, spots[i].Right = 0, spots[i].Top = INF, spots[i].Bottom = 0;
    51     cin >> H >> W;
    52     for (int i = 1; i <= H; i++)
    53     {
    54         scanf("%s",frame[i]+1);
    55         for (int j = 1; j <= W; j++)
    56         {
    57             if (frame[i][j] == '.')
    58                 continue;
    59             int c = (int)(frame[i][j]) - (int)('A') + 1;
    60             spots[c].Left = min(spots[c].Left,j);
    61             spots[c].Right = max(spots[c].Right,j);
    62             spots[c].Top = min(spots[c].Top,i);
    63             spots[c].Bottom = max(spots[c].Bottom,i);
    64             v[c] = 1;
    65         }
    66     }
    67     for (int i = 1; i <= 26; i++)
    68     {
    69         if (v[i])
    70         {
    71             for (int j = spots[i].Left; j <= spots[i].Right; j++)
    72             {
    73                 if (frame[spots[i].Top][j] != '.')
    74                     flag[i][frame[spots[i].Top][j]-'@'] = true;
    75                 if (frame[spots[i].Bottom][j] != '.')
    76                     flag[i][frame[spots[i].Bottom][j]-'@'] = true;
    77                     
    78             }
    79             for (int j = spots[i].Top; j <= spots[i].Bottom; j++)
    80             {
    81                 if (frame[j][spots[i].Left] != '.')
    82                     flag[i][frame[j][spots[i].Left]-'@'] = true;
    83                 if (frame[j][spots[i].Right] != '.')
    84                     flag[i][frame[j][spots[i].Right]-'@'] = true;
    85             }
    86         }
    87     }
    88     for (int i = 1; i <= 26; i++)
    89         for (int j = 1; j <= 26; j++)
    90             if (i != j && flag[i][j])
    91                 D[j]++;
    92     CountP = 0;
    93     dfs();
    94     return 0;
    95 }
  • 相关阅读:
    循环语句
    流程控制
    特殊的赋值运算符
    位运算符
    运算符
    八种基本类型
    cmd基础命令
    springboot项目部署到tomcat步骤以及常见问题
    【算法问题】如何实现大整数相加
    【算法问题】删除k个数字后的最小值
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/8413079.html
Copyright © 2011-2022 走看看