CCS-CSP 2013-12 批次 题目5 I’m stuck!

该博客详细解析了一道关于地图路径问题的算法题。给定一个R行C列的地图,玩家从'S'出发,目标是'T',但需要避开某些区域。博客介绍了如何通过深度搜索(DFS)策略,找到既可以从'S'到达,又不能到达'T'的方格数量。同时,提出了剪枝优化策略以提高效率。
摘要由CSDN通过智能技术生成

题目描述

问题描述

给定一个R行C列的地图,地图的每一个方格可能是’#’, ‘+’, ‘-’, ‘|’, ‘.’, ‘S’, ‘T’七个字符中的一个,分别表示如下意思:
  ‘#’: 任何时候玩家都不能移动到此方格;
  ‘+’: 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非’#‘方格移动一格;
  ‘-’: 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非’#‘方格移动一格;
  ‘|’: 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非’#‘方格移动一格;
  ‘.’: 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为’#’,则玩家不能再移动;
  ‘S’: 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非’#‘方格移动一格;
  ‘T’: 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非’#'方格移动一格。
  此外,玩家不能移动出地图。
  请找出满足下面两个性质的方格个数:

1. 玩家可以从初始位置移动到此方格;
  2. 玩家可以从此方格移动到目标位置。

输入格式

输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
  接下来的R行每行都包含C个字符。它们表示地图的格子。地图上恰好有一个’S’和一个’T’。

输出格式

如果玩家在初始位置就已经不能到达终点了,就输出“I’m stuck!”(不含双引号)。否则的话,输出满足性质的方格的个数。

样例输入

5 5

–±+
…|#.
…|##
S-±T
####.

样例输出

2

样例说明

如果把满足性质的方格在地图上用’X’标记出来的话,地图如下所示:

–±+
  …|#X
  …|##
  S-±T
  ####X

解题方案

1. 解题思路

满足性质的方格需要满足两种条件:

  • 玩家可以从初始位置移动到此方格;
  • 玩家不可以从此方格移动到目标位置。

也就是说满足性质的方格X表示

  1. 可以从S点到达
  2. 从该点可以到达T

所以解题思路可以先从S开始深搜遍历,统计经过的所有点,这些点构成的集合都满足条件1。然后在对点集进行遍历,对每个点进行判断,是否可以到达点T,如果不可以,将结果+1,最后输出结果就是所求答案。

优化方法:暂时想到的优化方法是使用剪枝,就是在S深搜之后,获得点集P,在对点P中的所有点进行遍历时,设置一个标记数组,这个标记表示是否可以到达终点T;这时候,如果点A标记为可以到达终点T,点B的下一个点是点A,那么点B同样可以到达终点T。对点集P中的点每次进行深搜遍历时,每一次遍历都会对路径上的所有点设置标记,这样如果某次遍历遍历到了一个中间点Q,并且这个点Q正好是被标记的点,那么就可以直接结束遍历,并且设置该点为标记点即可。

2. 解题步骤

  1. 从S点做深搜,得到S可以到达的点集P。
  2. 判断点集P中是否有终点T,如果没有直接输出“I’m stuck”;
  3. 如果P中含有点T,则对P中的每个点进行遍历,判断其是否可以到达终点T
  4. 统计符合条件的点的个数,输出

3. 示例代码

这部分代码写的有些乱,需要整理

public class Question5 {
   

    private static final int MAP_SIZE = 50;

    private static char[][] map = new char[MAP_SIZE + 1][];

    private static Position startPosition = null;

    private static Position endPosition = null;

    private static int n, m;

    /**
     * 获取点的移动量
     *
     * @param x 横坐标
     * @param y 纵坐标
     * @return 横纵坐标移动分量数组
     */
    private static int[][] direct(int x, int y) {
   
        int[][] result;
        switch (map[x][y]) {
   
            case '-':
                result = new int[][]{
   {
   0,-1}, {
   0,1}};
                break;
            case '|':
                result = new int[][]{
   {
   -1,0}, {
   1,0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值