CSP-I’m stuck!(Python实现100分)

问题描述
  给定一个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

思路:先从S出发进行BFS,将访问过的点在visited数组中标记为1,然后再从T出发(如果S可以到达T的话)进行BFS,不过在遍历周围点的时候得用逆向思维(就是不是看这个点能不能到达周围点,而是看周围点能否到达这个点,如果能的话加入队列),将遍历过的点在visited数组中标记为2,最后只需要统计visited中值为1的点的数量就行。
代码:

class Node:
    def __init__(self,x,y):
        self.x = x
        self.y = y

R,C = map(int,input().split())
maps = []
S_ind = [] # S的坐标
T_ind = [] # T的坐标
for i in range(R):
    temp = list(input())
    if 'S' in temp:
        x = i
        y = temp.index('S')
        S_ind.append(x)
        S_ind.append(y)
    if 'T' in temp:
        x = i
        y = temp.index('T')
        T_ind.append(x)
        T_ind.append(y)
    maps.append(temp)
_type = {
    'S':[[1,0],[-1,0],[0,1],[0,-1]],
    'T':[[1,0],[-1,0],[0,1],[0,-1]],
    '+':[[1,0],[-1,0],[0,1],[0,-1]],
    '-':[[0,1],[0,-1]],
    '|':[[1,0],[-1,0]],
    '.':[[1,0]]
}
# 用来计算上下左右四个点的坐标
round_T = [[1,0],[-1,0],[0,1],[0,-1]]
visited = [[0]*C for i in range(R)] # 初始化

def bounds(x,y):
    if x>=0 and y >= 0 and x<R and y<C:
        return True
    else:
        return False
# 从S点出发遍历
def BFS_S():
    flag = False  # 标记能不能到达目的地
    x = S_ind[0]
    y = S_ind[1]
    queue = []
    queue.append(Node(x,y))
    visited[x][y] = 1
    while queue:
        temp = queue.pop(0)
        x_t = temp.x
        y_t = temp.y
        c = maps[x_t][y_t]
        if c == 'T':
            flag = True
        if c != '#':
            t = _type[c]
            # 这个点周围可以走的点
            for i in t:
                x_i = x_t + i[0]
                y_i = y_t + i[1]
                # 如果这个位置不是不能通行的,并且还没有被访问过
                if bounds(x_i,y_i) and maps[x_i][y_i] != '#' and visited[x_i][y_i] == 0:
                    visited[x_i][y_i] = 1
                    queue.append(Node(x_i,y_i))
    return flag
# 从T点出发遍历
def BFS_T():
    x = T_ind[0]
    y = T_ind[1]
    queue = []
    queue.append(Node(x,y))
    visited[x][y] = 2
    while queue:
        temp = queue.pop(0)
        x_t = temp.x
        y_t = temp.y
        # 查看这个点周围 可以到达这个点的点
        for i in round_T:
            x_i = x_t + i[0]
            y_i = y_t + i[1]
            # 如果这个位置不是不能通行的,并且还没有被访问过
            if bounds(x_i,y_i) and maps[x_i][y_i] != '#' and visited[x_i][y_i] != 2:
                # 如果周围点是+ 或者 S 那么说明它上下左右都可以走,肯定能到达这个点的位置
                if maps[x_i][y_i] == '+' or maps[x_i][y_i] == 'S':
                    visited[x_i][y_i] = 2
                    queue.append(Node(x_i, y_i))
                # 如果周围点是 . 那么这个点必须在 . 的下方,因为 . 只能往下走
                elif maps[x_i][y_i] == '.':
                    if x_i+1 == x_t:
                        visited[x_i][y_i] = 2
                        queue.append(Node(x_i,y_i))
                elif maps[x_i][y_i] == '-' :
                    # 如果周围点是 - 那么在这个点必须在 - 的左方或者右方
                    if ((y_i-1 == y_t) or (y_i+1 == y_t)):
                        visited[x_i][y_i] = 2
                        queue.append(Node(x_i,y_i))
                # 如果周围点是 | 那么这个点必须在 | 的上方或者下方
                elif maps[x_i][y_i] == '|' :
                    if ((x_i-1 == x_t) or (x_i+1 == x_t)):
                        visited[x_i][y_i] = 2
                        queue.append(Node(x_i, y_i))
# 如果可到达目标点
if BFS_S():
    BFS_T()
    sum = 0
    for line in visited:
        sum += line.count(1)
    print(sum)
else:
    print("I'm stuck!")

提交结果图:
提交结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值