EricYang

Tech Spot of Eric

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
Finding Nemo
Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 6289   Accepted: 1426

Description

Nemo is a naughty boy. One day he went into the deep sea all by himself. Unfortunately, he became lost and couldn't find his way home. Therefore, he sent a signal to his father, Marlin, to ask for help. 
After checking the map, Marlin found that the sea is like a labyrinth with walls and doors. All the walls are parallel to the X-axis or to the Y-axis. The thickness of the walls are assumed to be zero. 
All the doors are opened on the walls and have a length of 1. Marlin cannot go through a wall unless there is a door on the wall. Because going through a door is dangerous (there may be some virulent medusas near the doors), Marlin wants to go through as few doors as he could to find Nemo. 
Figure-1 shows an example of the labyrinth and the path Marlin went through to find Nemo. 

We assume Marlin's initial position is at (0, 0). Given the position of Nemo and the configuration of walls and doors, please write a program to calculate the minimum number of doors Marlin has to go through in order to reach Nemo.

Input

The input consists of several test cases. Each test case is started by two non-negative integers M and N. M represents the number of walls in the labyrinth and N represents the number of doors. 
Then follow M lines, each containing four integers that describe a wall in the following format: 
x y d t 
(x, y) indicates the lower-left point of the wall, d is the direction of the wall -- 0 means it's parallel to the X-axis and 1 means that it's parallel to the Y-axis, and t gives the length of the wall. 
The coordinates of two ends of any wall will be in the range of [1,199]. 
Then there are N lines that give the description of the doors: 
x y d 
x, y, d have the same meaning as the walls. As the doors have fixed length of 1, t is omitted. 
The last line of each case contains two positive float numbers: 
f1 f2 
(f1, f2) gives the position of Nemo. And it will not lie within any wall or door. 
A test case of M = -1 and N = -1 indicates the end of input, and should not be processed.

Output

For each test case, in a separate line, please output the minimum number of doors Marlin has to go through in order to rescue his son. If he can't reach Nemo, output -1.

Sample Input

8 9
1 1 1 3
2 1 1 3
3 1 1 3
4 1 1 3
1 1 0 3
1 2 0 3
1 3 0 3
1 4 0 3
2 1 1
2 2 1
2 3 1
3 1 1
3 2 1
3 3 1
1 2 0
3 3 0
4 3 1
1.5 1.5
4 0
1 1 0 1
1 1 1 1
2 1 1 1
1 2 0 1
1.5 1.7
-1 -1

Sample Output

5
-1

Source

 

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 #define MAX_N 210
  6 using namespace std;
  7 
  8 int v[MAX_N + 1][MAX_N + 1]; //v[i][j]为到达格子[i][j]的最小步骤数
  9 int round[MAX_N + 1][MAX_N][4]; //用左上角点的坐标来指代格子,第三维0、1、2、3指定了该数组元素对应上、下、左、右边,数组的值表明了该边的类型 0空气 1墙 2门
 10 int wn, dn, startXI, startYI, minSteps;//wn墙数量 dn门的数量 起点对应的格子坐标
 11 double startXF, startYF;//起点的输入浮点坐标
 12 int dirarray[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};//方向数组,走四个方向时坐标的变换 分别为上、下、左、右
 13 
 14 //加入bfs队列的元素类型
 15 struct elem{
 16     //x、y为这个格子的坐标,dir记录了是从当前格子的那个方向进入到这个格子的, 上0 下1 左2 右3
 17     int x, y, dir, stepnum;//stepnum为到达当前格子所需要的步骤数量
 18 };
 19 queue<elem> bfsq;
 20 
 21 //取当前方向的对面方向
 22 void changeDir(int orginal, int &newDir){
 23     if(orginal == 0) newDir = 1;
 24     else if(orginal == 1) newDir = 0;//这里下的反方向肯定是上,POJ测试用例不全面,这里改成1也能AC
 25     else if(orginal == 2) newDir = 3;
 26     else newDir = 2;
 27 }
 28 
 29 //判断当前坐标是否在合法范围之内
 30 bool inRange(int x, int y){
 31     return x >= 0 && x <= 205 && y >= 0 && y<= 205;
 32 }
 33 
 34 void bfs(){
 35     //将Nemo的位置加入队列作为bfs搜索的起始位置
 36     while(!bfsq.empty()) bfsq.pop();
 37     elem curelem, newelem;
 38     curelem.x = startXI; curelem.y = startYI; curelem.dir = -1; curelem.stepnum = 0;
 39     v[startXI][startYI] = 0;
 40     bfsq.push(curelem);
 41 
 42     int curx, cury, curdir, cursteps, newx, newy, newdir, newsteps, d;
 43     while(!bfsq.empty()){//实现图的广度遍历即层次式的遍历都要借助于队列
 44         curelem = bfsq.front();
 45         bfsq.pop();
 46         curx = curelem.x; cury = curelem.y; curdir = curelem.dir; cursteps = curelem.stepnum;
 47 
 48         //到达原点
 49         if(curx == 0 && cury == 0){
 50             if(cursteps < minSteps)
 51                 minSteps = cursteps;
 52             continue;
 53         }
 54         //遍历当前格子的四个方向,尝试向四个方向走
 55         for(d = 0; d < 4; d++){
 56             //不能向回走
 57             if(d != curdir){
 58                 //所走的方向不能是墙
 59                 if(round[curx][cury][d] != 1)
 60                 {
 61                     //得到新的格子的坐标
 62                     newx = curx + dirarray[d][0];//要注意这种方向数组的用法,很巧妙!
 63                     newy = cury + dirarray[d][1];
 64 
 65                     //判定新坐标是否在合法的范围内
 66                     if(inRange(newx, newy))
 67                     {
 68                         //计算所有相对目标格子所在的方位
 69                         changeDir(d, newdir);
 70 
 71                         //如果是门,步骤数+1
 72                         if(round[curx][cury][d] == 2)
 73                             newsteps = cursteps + 1;
 74                         else //如果是空气步骤数目不变
 75                             newsteps = cursteps;
 76 
 77                         //判断当前的新格子的新状态是否需要加入队列
 78                         if(v[newx][newy] == 0xbf || newsteps < v[newx][newy] && newsteps < minSteps){
 79                             v[newx][newy] = newsteps;
 80                             newelem.x = newx; newelem.y = newy; newelem.stepnum = newsteps; newelem.dir = newdir;
 81                             bfsq.push(newelem);
 82                         }
 83                     }
 84                 }
 85             }
 86         }
 87     }
 88 }
 89 
 90 int main(){
 91     int i, j, x, y, d, t;
 92     while(scanf("%d%d", &wn, &dn) && !(wn == -1 && dn == -1)){
 93         minSteps = 65535;
 94         memset(v, 12, sizeof(v));
 95         memset(round, 0, sizeof(round));
 96         for(i = 1; i <= wn; i++){
 97             cin>>x>>y>>d>>t;
 98             //输入预处理,把门和墙转化为格子对应的四面边界
 99             if(d == 1)//与y轴平行
100                 for(j = y + 1; j <= y + t; j++)//数组的值为格子类型 0为空气 1为墙 2为门
101                     round[x][j][2] = round[x - 1][j][3] = 1;//第三维为方向 0上 1下 2左 3右
102             else
103                 for(j = x; j < x + t; j++)
104                     round[j][y][0] = round[j][y + 1][1] = 1;
105         }
106         for(i = 1; i <= dn; i++){
107             cin>>x>>y>>d;
108             if(d == 1)
109                 round[x][y + 1][2] = round[x - 1][y + 1][3] = 2;
110             else
111                 round[x][y][0] = round[x][y + 1][1] = 2;
112 
113         }
114         cin>>startXF>>startYF;//Nemo位置
115         startXI = startXF;
116         startYI = startYF +1;
117         //一场输入处理
118         if(startXI < 0 || startXI > 199 || startYI < 0 ||startYI > 199)
119             cout<<0<<endl;
120         else{
121             bfs();
122             if(minSteps == 65535) cout<<"-1"<<endl;
123             else cout<<minSteps<<endl;
124         }
125     }
126     return 0;
127 }
posted on 2012-08-19 22:37  Eric-Yang  阅读(320)  评论(0编辑  收藏  举报