CCF CSP 201312-5 I’m stuck! (Python)

该博客介绍了如何使用Python解决一个地图路径问题。玩家从'S'点出发,目标是'T'点,但不能到达目标后还继续移动。博主分享了找到可行路径并排除不可达目标的策略,使用栈来实现,但遇到了超时问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

  给定一个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.找出从S可达的点

        2.从上一步找出的点集中的所有点中去除可达T的点

主要思路是采用栈的思想。首先将起始点进栈,对于栈顶的一步可达点进栈。出栈的条件是:栈顶元素不存在可达点未进栈。

最后的得分是80分,显示运行超时。可以推测大方向还是对的,有时间再对代码进行优化。

# 80 运行超时


R, C = input().split()
maze = []
for i in range(int(R)):
    maze.append(list(input().strip()))

flag = [[0 for _ in range(int(C))] for _ in range(int(R))]  # 对不可访问点和已访问点进行标注

for i in range(int(R)):
    for j in range(int(C)):
        if maze[i][j] == 'S':
            x1, y1 = i, j
        if maze[i][j] == 'T':
            x2, y2 = i, j
        if maze[i][j] == '#':
            flag[i][j] = 1

def move_next(d):
    dirs = []
    if d == '+' or d == 'T' or d == 'S':
        dirs = [lambda x, y: (x - 1, y),
                lambda x, y: (x + 1, y),
                lambda x, y: (x, y - 1),
                lambda x, y: (x, y + 1)
                ]
    if d == '-':
        dirs = [lambda x, y: (x, y - 1),
                lambda x, y: (x, y + 1)
                ]
    if d == '|':
        dirs = [lambda x, y: (x - 1, y),
                lambda x, y: (x + 1, y)
                ]
    if d == '.':
        dirs = [lambda x, y: (x + 1, y)]
    return dirs


stackS = []
stackD = []

curNode = (x1, y1)  # 起始点S

stackS.append(curNode)
stackD.append(curNode)
flag[x1][y1] = 1

while len(stackS) > 0:  # 找出S可达点
    curNode = stackS[-1]
    dirs = move_next(maze[curNode[0]][curNode[1]])
    is_stack_pop = True
    for dir in dirs:
        nextNode = dir(curNode[0], curNode[1])  # 下一个可达节点
        if nextNode[0] >= 0 and nextNode[0] < int(R) and nextNode[1] >= 0 and nextNode[1] < int(
                C) and flag[nextNode[0]][nextNode[1]] == 0:
            is_stack_pop = False
            stackS.append(nextNode)  # 可达节点进栈
            stackD.append(nextNode)  # 可达点集
            flag[nextNode[0]][nextNode[1]] = 1  # 将已经访问过的节点进行标记
            # set1.add(nextNode)  # 加入S可达节点集
    if is_stack_pop == True:
        stackS.pop()
results = stackD.copy()
for _, tuple_loc in enumerate(stackD):  # 找出S可达点中的不可达T点
    flag1 = [[0 for _ in range(int(C))] for _ in range(int(R))] # 对不可访问点和已访问点进行标注
    for i in range(int(R)):
        for j in range(int(C)):
            if maze[i][j] == '#':
                flag1[i][j] = 1
    stackR = []
    stackR.append(tuple_loc)
    flag1[tuple_loc[0]][tuple_loc[1]] = 1
    while len(stackR) > 0:
        curNode = stackR[-1]
        dirs = move_next(maze[curNode[0]][curNode[1]])
        is_stack_pop = True
        is_break = False
        if maze[curNode[0]][curNode[1]] == 'T':
            results.remove(tuple_loc)
            is_break = True
        for dir in dirs:
            nextNode = dir(curNode[0], curNode[1])

            if nextNode[0] >= 0 and nextNode[0] < int(R) and nextNode[1] >= 0 and nextNode[1] < int(
                    C) and flag1[nextNode[0]][nextNode[1]] == 0:
                is_stack_pop = False
                stackR.append(nextNode)
                flag1[nextNode[0]][nextNode[1]] = 1
                if maze[nextNode[0]][nextNode[1]] == 'T':
                    results.remove(tuple_loc)
                    is_break = True
                    break
        if is_break:
            break
        if is_stack_pop == True:
            stackR.pop()
if (x2, y2) not in stackD:
    print("I'm stuck!")
else:
    print(len(results))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值