[Swust OJ 191]--迷宫逃离(打表搜索)

 
Time limit(ms): 1000      Memory limit(kb): 65535
 

江鸟突然想到了一个迷宫逃离的游戏,话说有三个人被困于一个n*m的迷宫里,他们三人都可以向上、向下、向左、向右四个方向进行走动,当然他们所在的初始位置没有障碍物,同时只能走到没有障碍物的格子上,现在江鸟要问你最少需要去掉多少个格子的障碍物,可以使他们三人之间两两互相可达。

Description

输入包括多组测试数据,每组测试数据第一行为两个整数n和m(2<=n,m<=100),接下来n行,每行m个字符,其中:‘w’、‘W’、‘f’分别代表那三个人;‘.’代表没有障碍物的格子,‘#’代表有障碍物的格子。

Input

每组数据输出一行。

Output
1
2
3
4
5
6
7
8
9
10
11
4 4
w...
####
.##f
W##.
4 4
w...
....
.##f
.W..
 
Sample Input
1
2
3
2
0
 
Sample Output
Hint
信息学院院赛
 
集体思路:直接打表3个人每个人到每一个点需要去掉障碍的个数,然后枚举可到达点计算最小值即可~
     具体的可以看代码内注释
代码如下:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 using namespace std;
 6 
 7 #define inf 0x3f3f3f3f
 8 #define maxn  110
 9 struct node{
10     int x, y;
11 };
12 int n, m;
13 node p[4];
14 char mpt[maxn][maxn];
15 int vis[maxn][maxn][4];//vis分别代表每个人到每一个点需要消掉的障碍物
16 int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };
17 
18 void bfs(int index)
19 {
20     queue<node> q;
21     node now, next;
22     now.x = p[index].x;
23     now.y = p[index].y;
24     q.push(now);
25     vis[now.x][now.y][index] = 0;
26     while (!q.empty()){
27         now = q.front();
28         q.pop();
29         for (int i = 0; i < 4; i++){
30             next = now;
31             next.x += dir[i][0];
32             next.y += dir[i][1];
33             if (next.x<1 || next.x>n || next.y<1 || next.y>m) continue;
34             int tmp = vis[now.x][now.y][index];
35             if (mpt[next.x][next.y] == '#')tmp++;//遇到一个障碍物,那么此人到达这个点需要消掉的障碍物加1
36             if (tmp < vis[next.x][next.y][index]){
37                 //判断是否可以让需要消掉的障碍物更小
38                 vis[next.x][next.y][index] = tmp;
39                 q.push(next);
40             }
41         }
42     }
43 }
44 int main(){
45     while (~scanf("%d%d", &n, &m)){
46         memset(vis, inf, sizeof(vis));
47         for (int i = 1; i <= n; i++) scanf("%s", mpt[i] + 1);
48         for (int i = 1; i <= n; i++){
49             for (int j = 1; j <= m; j++){
50                 if (mpt[i][j] == 'w') p[1].x = i, p[1].y = j;
51                 else if (mpt[i][j] == 'W') p[2].x = i, p[2].y = j;
52                 else if (mpt[i][j] == 'f') p[3].x = i, p[3].y = j;
53             }
54         }
55         //对每一个人计算出到每一个点需要消掉的最少障碍物
56         bfs(1);
57         bfs(2);
58         bfs(3);
59         int ans = inf;
60         for (int i = 1; i <= n; i++){
61             //如果三个人两两可以到达,那么他们可以集聚在一个点,下面枚举每一个这样的点
62             for (int j = 1; j <= m; j++){
63                 int tmp = 0;
64                 for (int k = 1; k <= 3; k++) tmp += vis[i][j][k];
65                 if (mpt[i][j] == '#') tmp -= 2;//如果在一个'#'集聚,那么就会多计算2个
66                 ans = ans < tmp ? ans : tmp;
67             }
68         }
69         printf("%d\n", ans);
70     }
71     return 0;
72 }
View Code

 

转载于:https://www.cnblogs.com/zyxStar/p/4572564.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值