巡逻的机器人

 

  题意:

         机器人要从一个m*n(1<=m,n<=20)网格的左上角(1,1)到右下角(m,n)。网格中的一些格子是空地(用0表示),其他格子是障碍(用1表示)。机器人每次可以往四个方向走一格,但不能连续穿越k个(0<=K<=20)障碍,求最短的长度。起点和终点保证是空地。如图:最短的长度是10.

                      

      

 

Input 

The input consists of several data sets. The first line of the input file contains the number of data sets which is a positive integer and is not bigger than 20. The following lines describe the data sets.

For each data set, the first line contains two positive integer numbers m and n separated by space (1$ \le$m, n$ \le$20). The second line contains an integer number k(0$ \le$k$ \le$20). The ith line of the next m lines contains n integer aij separated by space (i = 1, 2,..., m;j = 1, 2,...,n). The value of aij is 1 if there is an obstacle on the cell (i, j), and is 0 otherwise.

 

Output 

For each data set, if there exists a way for the robot to reach the cell (m, n), write in one line the integer number s, which is the number of moves the robot has to make; -1 otherwise.

 

Sample Input 

 

3 
2 5 
0 
0 1 0 0 0 
0 0 0 1 0 
4 6 
1 
0 1 1 0 0 0
0 0 1 0 1 1
0 1 1 1 1 0
0 1 1 1 0 0
2 2 
0 
0 1 
1 0

 

Sample Output 

 

7 
10 
-1

          思路分析:

            寻找最优解,采用BFS。

        

           前提准备:

           1、首先输入的K值就是机器人的血量,连续穿越K+1个障碍之后,机器人就会挂掉。然而如果第一次连续穿越了

K-1个障碍后又遇到0,那么就要给机器人加满血。

           2、用一个三维数组来标记机器人来过这里,可赋值为1。第三维的数据用机器人走这条路剩余的血量表示。

           3、用队列存储每一个结点,(即每一个中心,因为机器人每到达一个地方(中心)就有四个方向可走)

          分析:

                1、模拟机器人巡逻,碰到“1”就减血量。

                2、每到达一个点,需要判断:点是否越界(就要换方向),点是否是终点(直接结束),点是否之前来过(换方向)

                3、把可以走的点存进队列,继续上面的过程。

    

                源代码:

             

 1 #include<iostream>
 2 #include<queue>
 3 #include<cstring>
 4 #define MAXN 25
 5 using namespace std;
 6 int to[4][2] = { -1, 0, 0, -1, 1, 0, 0, 1 };
 7 int n, m, z;
 8 int chess[MAXN][MAXN];
 9 int dot[MAXN][MAXN][MAXN];
10 struct node{
11     int x;
12     int y;
13     int z;
14     int step;
15 }R,R1,t;
16 int judge(int a, int b)
17 {
18     if (a >= n || a < 0 || b >= m || b < 0 )
19         return 1;
20     return 0;
21 
22 }
23 int bfs()
24 {
25     queue<node>Q;
26     R.x = 0;
27     R.y = 0;
28     R.z = z;
29     R.step = 0;
30     dot[0][0][z] = 1;
31     Q.push(R);
32     while (!Q.empty())
33     {
34         t = Q.front();
35         Q.pop();
36         if (t.x == n - 1 && t.y == m - 1)  //到达目的地
37             return t.step;
38         for (int i = 0; i < 4; i++)
39         {
40             R1.x = t.x + to[i][0];        
41             R1.y = t.y + to[i][1];    //* 之前是[0][i]
42 
43             if (R1.x == n - 1 && R1.y == m - 1)
44                 return t.step + 1;
45             if (judge(R1.x, R1.y))       //判断越界,越界就换方向
46                 continue;
47 
48             if (chess[R1.x][R1.y])  //*之前是dot[][]
49                 R1.z = t.z - 1;  //* 之前是z-1 ,减一表示机器人的血量
50             else
51                 R1.z = z;
52             if (R1.z < 0)    
53                 continue;
54             if (dot[R1.x][R1.y][R1.z])  //*之前这句放在了越界的地方是错的,那里的Z还没赋值
55                 continue;                //判断机器人走过,就换方向
56             dot[R1.x][R1.y][R1.z] = 1;  //标记机器人走过这里
57             R1.step = t.step + 1;   //*
58             Q.push(R1);
59 
60         }
61     
62     if (Q.empty())            //*之前放在了循环里
63     {
64 
65         t.step = -1;
66         return t.step;
67     }
68 }
69 }
70 int main()
71 {
72     int t;
73     cin >> t;
74     while (t--)
75     {
76         memset(chess, 0, sizeof(chess));
77         memset(dot, 0, sizeof(dot));
78         cin >> n >> m;
79         cin >> z;
80         for (int i = 0; i < n; i++)
81         {
82             for (int j = 0; j < m; j++)
83                 cin >> chess[i][j];
84         }
85         cout << bfs() << endl;
86         
87 
88     }
89     return 0;
90 }

 

 心得:

      这是第二次用BFS,不做不知道,做了才发现上一次对BFS的理解还不是很深刻,进而导致代码中出现了各种错误(*标记处),头文件也会忘记,cstring。这次做完这个题目,认真看了遍,比上次理解得更深刻了,用BFS要注意初始化,越界问题,定义的变量多少的问题,还有就是哪些变量跟着哪个点走,当然还有清零的问题。这次发现的问题比较多,总之加油吧!

 

 

                         

posted @ 2015-07-26 21:58  白一  阅读(316)  评论(0编辑  收藏  举报