2019西北工业大学程序设计创新实践基地春季选拔赛(重现赛) H题----Chino with Ciste

链接:https://ac.nowcoder.com/acm/contest/553/H
来源:牛客网
 

Chino with Ciste

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

Chino的数学很差,因此Cocoa非常担心。但是今天Cocoa不准备教Chino什么啦(欢呼!)!
事情是这样的,Cocoa在打扫爷爷的咖啡屋卫生的时候偶然从相框里掉出来一张地图——小镇的传统寻宝游戏Ciste.
游戏的规则也很简单,首先有一个起点,然后是下一个藏有地图的位置。如此下去,最终找到藏宝地点。
Cocoa还没有玩过这个游戏呢,因此她非常期待……寻宝的过程非常快乐,Cocoa也找到了宝物,“宝物就是你决定性的瞬间!”。不过,现在,拿着所有地图的Cocoa看着小镇的地图,给Chino布置了一个作业,以检查自己教学的效果:
假设小镇的地图是一个的网格,其中有一些格子是空地,用’.’表示,可以朝上下左右四个方向中的若干个方向走;另外一些格子是房屋,用’*’表示,不能通过。现在Cocoa在’S’,宝物在’T’,请问Cocoa应该如何选择路线,才能使自己转最少的弯呢?
题目对Chino来说太难啦,你能帮一帮Chino吗?

输入描述:

第一行是两个正整数n, m;接下来是一个n×mn×m的矩阵,表示小镇的地图

输出描述:

最少的拐弯次数。如果不能到达,请输出"troil"(不带引号).

示例1

输入

复制

4 4
S..*
.*.*
....
.*.T

输出

复制

2

想法:用dfs不断更新最小转弯次数必然会超时,正解应该使用bfs,开一个二维数组turndir记录到达每一个点的最少转弯次数,然后在bfs里面每次确定一个方向上的下一个点,就通过while循环来实现在该方向上一直走下去同时更新turndir(与该方向上的第一个点的转向次数一致),最后到达终点时就是最优的转弯次数,直接输出即可。

代码:

#include<bits/stdc++.h>
using namespace std;
int n, m, sx, sy;
char Map[2010][2010];
int turndir[2010][2010];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
struct point {
  int x, y;
};
void bfs() {
  queue<point> q;
  point now, next;
  now.x = sx;
  now.y = sy;
  q.push(now);
  while(!q.empty()) {
    now = q.front();
    q.pop();
    if(Map[now.x][now.y] == 'T') {
      printf("%d\n", turndir[now.x][now.y]);
      return;
    }
    for(int i = 0; i < 4; i++) {
      next.x = now.x + dir[i][0];
      next.y = now.y + dir[i][1];//先明确下一方向上的第一个点 
      while(1) {//将这一方向走到底即该方向上的点全部走一遍,隐含的最优 
        if(next.x < 1 || next.x > n || next.y < 1 || next.y > m || Map[next.x][next.y] == '*') break;//越界、走不了
        if(turndir[next.x][next.y] == -1) {//该点未被访问过
          turndir[next.x][next.y] = turndir[now.x][now.y] + 1;//每次取出的now点然后走到next点必然是转向了的,因为如果没有转向,在之前的while里是会标记为访问过的(赋转向次数值) 
          q.push(next);//入队,后面可能需要在该点基础上再转弯    
        }
        next.x += dir[i][0];
        next.y += dir[i][1];//该方向上继续走 
      } 
    }
  }
  printf("troil\n");
  return; 
}
int main() {
  scanf("%d%d", &n, &m);
  for(int i = 1; i <= n; i++) {
    getchar();
    for(int j = 1; j <= m; j++) {
      scanf("%c", &Map[i][j]);
      turndir[i][j] = -1;//初始化转弯次数为-1,同时代表该点未被访问 
      if(Map[i][j] == 'S') {
        sx = i;
        sy = j;
      }
    }
  }
  bfs();
  return 0;
}

猜你喜欢

转载自blog.csdn.net/daixinliangwyx/article/details/89084137