18.06.25 POJ4129 16年期末09:变换的迷宫

描述

你现在身处一个R*C 的迷宫中,你的位置用"S" 表示,迷宫的出口用"E" 表示。

迷宫中有一些石头,用"#" 表示,还有一些可以随意走动的区域,用"." 表示。

初始时间为0 时,你站在地图中标记为"S" 的位置上。你每移动一步(向上下左右方向移动)会花费一个单位时间。你必须一直保持移动,不能停留在原地不走。

当前时间是K 的倍数时,迷宫中的石头就会消失,此时你可以走到这些位置上。在其余的时间里,你不能走到石头所在的位置。

求你从初始位置走到迷宫出口最少需要花费多少个单位时间。

如果无法走到出口,则输出"Oop!"。

输入第一行是一个正整数 T,表示有 T 组数据。
每组数据的第一行包含三个用空格分开的正整数,分别为 R、C、K。
接下来的 R 行中,每行包含了 C 个字符,分别可能是 "S"、"E"、"#" 或 "."。
其中,0 < T <= 20,0 < R, C <= 100,2 <= K <= 10。输出对于每组数据,如果能够走到迷宫的出口,则输出一个正整数,表示最少需要花费的单位时间,否则输出 "Oop!"。样例输入

1
6 6 2
...S..
...#..
.#....
...#..
...#..
..#E#.

样例输出

7
 1 #include <cstdio>
 2 #include <string>
 3 #include <memory.h>
 4 #include <algorithm>
 5 #include <stdlib.h>
 6 #include <math.h>
 7 #include <iostream>
 8 #include<queue>
 9 #include <set>
10 using namespace std;
11 
12 int r, c, k;
13 int visited[105][105][15];
14 int map[105][105];
15 int sx, sy, ex, ey;
16 int dir1[4] = { 0,0,1,-1 }, dir2[4] = { 1,-1,0,0 };
17 int flag = 0;
18 
19 struct node{
20     int time;
21     int x, y;
22     node(int _x, int _y) :x(_x), y(_y) { time = 0; }
23 };
24 queue<node> all;
25 
26 void bfs() {
27     while (!all.empty()) {
28         node now = all.front();
29         all.pop();
30         for (int i = 0; i < 4; i++) {
31             int xx = now.x + dir1[i], yy = now.y + dir2[i];
32             node newone(now);
33             newone.x = xx, newone.y = yy;
34             newone.time = now.time + 1;
35             int tmptime = newone.time%k;
36             if (xx == ex && yy == ey) {
37                 printf("%d\n", newone.time);
38                 flag = 1;
39                 return;
40             }
41             if (map[xx][yy]==1&&visited[xx][yy][tmptime] == 0||map[xx][yy]==2&& visited[xx][yy][tmptime] == 0&&tmptime==0)
42             {
43                 all.push(newone);
44                 visited[xx][yy][tmptime] = 1;
45             }
46         }
47     }
48 }
49 
50 int main()
51 {
52     int t;
53     scanf("%d", &t);
54     while (t--) {
55         all = queue<node>();
56         memset(visited, 0, sizeof(int) * 105 * 105 * 15);
57         memset(map, 0, sizeof(int) * 105 * 105 );
58         flag = 0;
59         scanf("%d%d%d", &r, &c, &k);
60         for(int i=1;i<=r;i++)
61             for (int j = 1; j <= c; j++) {
62                 char ch;
63                 cin >> ch;
64                 if (ch == '.')
65                     map[i][j] = 1;
66                 else if (ch == 'S')
67                 {
68                     map[i][j] = 1;
69                     sx = i, sy = j;
70                 }
71                 else if (ch == 'E') {
72                     map[i][j] = 1;
73                     ex = i, ey = j;
74                 }
75                 else
76                     map[i][j] = 2;
77             }
78         node origin(sx,sy);
79         all.push(origin);
80         visited[sx][sy][0] = 1;
81         bfs();
82         if (!flag)
83             printf("Oop!\n");
84     }
85     return 0;
86 }
View Code

思路:

很容易想到广搜,但是数据那么大,显然会TLE

那么怎么办呢?剪枝

很容易能知道,由于每过k单位时间,石头就会消失一次,那么当我们站在某点 (x,y) 时,时间为 t+k 和  t  时,它们之后行走面临的情境是完全一样的,那就意味着,对于某个状态的时间,我们可以取模后作为 visited[x][y][time] 的第三个变量,如果取模后的值代入发现已经访问过,那说明之前已经有更优越的情况出现过,不必再继续搜索了

posted @ 2018-06-25 18:21  TobicYAL  阅读(985)  评论(0编辑  收藏  举报