CCF-CSP 201312-5 I‘m stuck! (python)

问题描述

CCF-CSP 201312-5 I’m stuck!

问题描述

给定一个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. 不同的格子可以到达的格子不同
  2. 有些格子不能到达
  3. 不仅要考虑初始位置能遍历到的格子,还要考虑不能到达终点的格子

前两点只需要在传统图遍历算法中进行特判。第三点的解决需要加一个从终点反向遍历,以排除能到达终点的格子。

解法

#input
line = input()
nums = line.split()
R = eval(nums[0])
C = eval(nums[1])
matrix = []
for i in range(R):
    matrix.append(input())
#print(R,C)
#print(matrix)

#find S and T
for i in range(R):
        for j in range(C):
            if matrix[i][j] == 'S':
                xS,yS=i,j
for i in range(R):
        for j in range(C):
            if matrix[i][j] == 'T':
                xT,yT=i,j    

#traverse from S
def traverseS():
    def inner(x,y):
        if matrix[x][y] == '#':
            return
        res[x][y] = 1
        if x < R -1 and matrix[x][y] in 'ST+|.' and res[x+1][y] == 0:
            inner(x+1,y)
        if x > 0 and matrix[x][y] in 'ST+|' and res[x-1][y] == 0:
            inner(x-1,y)
        if y < C-1 and matrix[x][y] in 'ST+-' and res[x][y+1] == 0:
            inner(x,y+1)
        if y > 0 and matrix[x][y] in 'ST+-' and res[x][y-1] == 0:
            inner(x,y-1)
    res = [[0 for i in range(C)]for j in range(R)]
    inner(xS,yS)
    return res

#traverse from T reversely
def traverseT():
    def inner(x,y):
        if matrix[x][y] == '#':
            return
        res[x][y] = 1
        if x < R -1 and matrix[x+1][y] in 'ST+|' and res[x+1][y] == 0:
            inner(x+1,y)
        if x > 0 and matrix[x-1][y] in 'ST+|.' and res[x-1][y] == 0:
            inner(x-1,y)
        if y < C-1 and matrix[x][y+1] in 'ST+-' and res[x][y+1] == 0:
            inner(x,y+1)
        if y > 0 and matrix[x][y-1] in 'ST+-' and res[x][y-1] == 0:
            inner(x,y-1)
    res = [[0 for i in range(C)]for j in range(R)]
    
    inner(xT,yT)
    return res

#main 
propt1 = traverseS()
propt2 = traverseT()
if propt1[xT][yT] == 0:
    print("I'm stuck!")
else:
    count = 0
    for i in range(R):
        for j in range(C):
            if propt1[i][j] == 1 and propt2[i][j] == 0:
                count+=1
    print(count)
    

复杂度O(R2C2)

吐槽

准备2021.3的CCF-CSP。这是我模考里面刷的第一道题。没想到作为第5道题这么直白。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值