zoukankan      html  css  js  c++  java
  • BOI 2005 Maze SPFA

    题目

    BOI 2005 Day 1
    Maze
    Pasvalys Language: ENG
    Lithuania
    7.5.2005 Page 1 of 2 MAZE
    Maze (Lithuania)
    Consider the following maze made of equilateral triangles:
    Each vertex is described by two coordinates x and y as in the picture. Some of the edges
    have a white or a black circle on them. There are two major rules that control movement
    within the maze:
    § it is only allowed to pass edges with circles on them.
    § while walking through the maze it is obligatory to alternate white and black
    circles; i.e. it is only allowed to pass an edge with white circle if the last circle
    passed was black and vice versa. It is allowed to pass an edge with either black or
    white circle on it during the first move.
    TASK
    Write a program to find the length of the shortest path from the entrance point to the exit
    in the maze. The length of the path is defined as the number of edges (or circles) passed.
    You may assume that such path always exists.
    INPUT
    The input file name is MAZE.IN The first line contains two integers W and H which are
    the width and the height of the maze respectively (1 £ W, H £ 500). The second line
    consists of four integer values: X1 Y1 X2 Y2 (0 £ X1, X2 £ W; 0 £ Y1, Y2 £ H ). (X1, Y1) are
    the coordinates of the entry point in the maze and (X2, Y2) are the exit coordinates.
    The next 2H+1 lines provide the description of the edges: odd lines (3rd, 5th, etc) describe
    horizontal edges, and even lines (4th, 6th, etc) describe non-horizontal ones. Each line
    consists of a string of characters n, w and b, where n means, that there is no circle on the
    edge, and w or b means that there is white or black circle on the edge respectively. There
    are no spaces between these characters. Naturally, odd lines consist of exactly W
    characters, and even lines consist of exactly 2W+1 characters.
    BOI 2005 Day 1
    Maze
    Pasvalys Language: ENG
    Lithuania
    7.5.2005 Page 2 of 2 MAZE
    OUTPUT
    Your program should output a single integer (the length of the shortest path from entrance
    point to the exit in the maze) in the first (and the only) line of the file MAZE.OUT.
    EXAMPLES
    INPUT OUTPUT COMMENTS
    2 1
    0 0 2 1
    bb
    nwwnw
    bn
    6 A simple maze. One possible shortest path is
    this:
    (0, 0) à (1, 0) à (0, 1) à (1, 1) à (1, 0) à
    (2, 0) à (2, 1)
    Here is the illustration of the maze and the
    shortest path:
    INPUT OUTPUT COMMENTS
    5 4
    0 2 5 2
    nnbnn
    nnnwwbwnnnn
    nbbbn
    nnwbwwbwwnn
    bwwww
    nnbwbbwwbnn
    nwwwn
    nnnnbwbbnnn
    nnwnn
    22 This is the description of the maze given in the
    picture on the first page. The shortest path is
    this:
    (0, 2) à (1, 2) à (1, 1) à (2, 1) à (2, 0) à
    (3, 0) à (3, 1) à (3, 2) à (4, 1) à (3, 1) à
    (3, 0) à (2, 0) à (2, 1) à (1, 1) à (1, 2) à
    (1, 3) à (2, 3) à (2, 4) à (3, 4) à (3, 3) à
    (4, 3) à (4, 2) à (5, 2)
    (Length: 22)

    分析

    其实这道题就是有些变化的最短路径问题,也就是这道题对于这个“路径”有一定的要求:必须黑白交替行进。

    这道题比较令人头疼的难点在于这个坐标。首先这不是正方形的格子,而是等边三角形,并且坐标表示方法也和习惯有些不同。通常我们写SPFA都会用到的是这个点的“代号”。这里用坐标就会显得比较难受。可以硬着头皮直接带着坐标写,但是我本着程序员十分钟做完的事情宁愿花一个小时来写程序解决的精神,我在读入的时候就把所有的点预处理好,以“代号”的形式来存储。从左上角,先往右,再往下,依次给每个点标号。这样做肯定有些烧脑,要理清点、边之间的关系。(读入边的颜色,所以要将边转化为点的坐标再转化为点的代号,然后进行建边)

    这样一来,所有事情就像我们往常做的一样了。裸着SPFA,在其中对于边的颜色加一个小小的判断(没有颜色的边我直接就没有添加,因为肯定不会经过)。

    程序

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 struct point
      4 {
      5     int x,y;
      6 }A,B;
      7 struct edge
      8 {
      9     int Next, Aim;
     10     bool Color;
     11     // TRUE: Black
     12     // FALSE: White
     13 }Edge[501*501*2];
     14 int W, H, EdgeCount, Head[501*501], start, target;
     15 int dist[501*501+1][2];
     16 char C;
     17 void Insert(int u, int v, char color)
     18 {
     19     if (color == 'w')
     20     {
     21         Edge[++EdgeCount] = (edge){Head[u], v, false};
     22         Head[u] = EdgeCount;
     23         Edge[++EdgeCount] = (edge){Head[v], u, false};
     24         Head[v] = EdgeCount;
     25     }
     26     if (color == 'b')
     27     {
     28         Edge[++EdgeCount] = (edge){Head[u], v, true};
     29         Head[u] = EdgeCount;
     30         Edge[++EdgeCount] = (edge){Head[v], u, true};
     31         Head[v] = EdgeCount;
     32     }
     33 }
     34 void SPFA()
     35 {
     36     //0: White
     37     //1: Black
     38     //freopen("maze.in","r",stdin);
     39     //freopen("maze.out","w",stdout);
     40     memset(dist, 0x3F, sizeof(dist));
     41     queue<int> Q;
     42     Q.push(start);
     43     dist[start][0] = dist[start][1] = 0;
     44     while(!Q.empty())
     45     {
     46         int u = Q.front();
     47         Q.pop();
     48         for (int i = Head[u]; i; i = Edge[i].Next)
     49         {
     50             int v = Edge[i].Aim;
     51             if (Edge[i].Color)
     52             {
     53                 if (dist[u][0]+1<dist[v][1])
     54                 {
     55                     dist[v][1] = dist[u][0]+1;
     56                     Q.push(v);
     57                 }
     58             }
     59             else
     60             {
     61                 if (dist[u][1]+1<dist[v][0])
     62                 {
     63                     dist[v][0] = dist[u][1]+1;
     64                     Q.push(v);
     65                 }
     66             }
     67         }
     68     }
     69 }
     70 /*
     71 2 1
     72 0 0 2 1
     73 bb
     74 nwwnw
     75 bn
     76 */
     77 int main()
     78 {
     79     cin >> W >> H;
     80     cin >> A.x >> A.y >> B.x >> B.y;
     81     start = A.y*(W+1)+A.x+1, target = B.y*(W+1)+B.x+1;
     82     for (int i = 1; i <= 2*H+1; i++)
     83     {
     84         if (i % 2)
     85         {
     86             for (int j = 1; j <= W; j++)
     87             {
     88                 cin >> C;
     89                 int p1 = (i-1)/2*(W+1)+j, p2 = (i-1)/2*(W+1)+j+1;
     90                 Insert(p1,p2,C);
     91             }
     92         }
     93         else
     94         {
     95             for (int j = 1; j <= 2*W+1; j++)
     96             {
     97                 cin >> C;
     98                 if (j % 2)
     99                 {
    100                     int p1 = (i/2-1)*(W+1)+(j+1)/2, p2 = i/2*(W+1)+(j+1)/2;
    101                     Insert(p1,p2,C);
    102                 }
    103                 else
    104                 {
    105                     int p1 = (i/2-1)*(W+1)+j/2+1, p2 = i/2*(W+1)+j/2;
    106                     Insert(p1,p2,C);
    107                 }
    108             }
    109         }
    110     }
    111     SPFA();
    112     /*
    113     for (int i = 1; i <= (W+1)*(H+1); i++)
    114         cout << dist[i][0] << " " << dist[i][1] << endl;
    115     */
    116     cout << min(dist[target][0],dist[target][1]) << endl;
    117     return 0;
    118 }
  • 相关阅读:
    ssh 命令
    mtr 命令
    ping 命令
    curl 命令
    echo 命令
    cp 命令
    sftp服务器配置
    tomcat性能优化
    消息队列
    深度学习
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/8401297.html
Copyright © 2011-2022 走看看