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 }

 

转载于:https://www.cnblogs.com/OIerPrime/p/8401297.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值