小言_互联网的博客

蓝桥杯-路径之谜——python

291人阅读  评论(0)

题目如下

小明冒充 X 星球的骑士,进入了一个奇怪的城堡。

城堡里边什么都没有,只有方形石头铺成的地面。

假设城堡地面是 n×n 个方格。如下图所示。

图1

按习俗,骑士要从西北角走到东南角。可以横向或纵向移动,但不能斜着走,也不能跳跃。每走到一个新方格,就要向正北方和正西方各射一箭。(城堡的西墙和北墙内各有 n 个靶子)同一个方格只允许经过一次。但不必走完所有的方格。如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?有时是可以的,比如上图中的例子。

本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)

输入描述
第一行一个整数 N (0≤N≤20),表示地面有 N×N 个方格。

第二行 N 个整数,空格分开,表示北边的箭靶上的数字(自西向东)

第三行 N 个整数,空格分开,表示西边的箭靶上的数字(自北向南)

输出描述
输出一行若干个整数,表示骑士路径。

为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3 ⋯
比如,上图中的方块编号为:

0 1 2 3

4 5 6 7

8 9 10 11

12 13 14 15

输入输出样例
示例
输入

4
2 4 3 4
4 3 3 3
输出

0 4 5 1 2 3 7 11 10 9 13 14 15

题目解析

这道题一看路线问题应该要使用dfs,但是直接暴力求解吗,题目出给的数据限制N最大为20,说明暴力没有问题。那我们直接暴力dfs。但是我们使用反向思维,我们不断的拔剑,把剑拔完或者有一个为零而且到了就可以了。当到达终点时,除了要判断该点的坐标是不是终点坐标,或者判断所有的箭都已经拔完。

path = [0 for _ in range(401)]# 记录走过的点
dx = [1, 0, -1, 0]
dy = [0, 1, 0, -1]# 我们的移动
cntx = [0 for _ in range(21)]
cnty = [0 for _ in range(21)]# 记录箭的数量
maps = [[False for _ in range(21)]for _ in range(21)]# 用于判断是否走过
sun = False
tot = 0# 箭的总数

def check():# 判断是否完成,如果有一个为零,就不能往下走了
    for i in range(0, n):
        if cntx[i] != 0 or cnty[i] != 0:
            return False
    return True

def dfs(x, y, num):
    global sun
    path[num] = y *n + x # 坐标点
    maps[x][y] = True 
    cntx[x] -= 1 # 我们这步走过来拔剑
    cnty[y] -= 1 # 我们这步走过拔剑

    if x == n and y == n and check():
        sun = True# 完成走了
        return
    for i in range(4):
        x1 = x + dx[i]
        y1 = y + dy[i]
        if not sun and not maps[x1][y1] and 0 <= x1 < n and 0 <= y1 < n:
            if cntx[x1] > 0 and cnty[y1] > 0:
                dfs(x1, y1, num+1)
                maps[x1][y1] = False# 回溯,至关重要
                cntx[x1] += 1
                cnty[y1] += 1

n = int(input())
for i in range(0, n):
    cntx[i] = int(input())
    tot += cntx[i]
for i in range(0, n):
    cnty[i] = int(input())
    tot += cnty[i]
dfs(0, 0, 0)
print(path[:tot//2])# 走了箭的一半的数量应该没毛病

转载:https://blog.csdn.net/qq_51718832/article/details/117307978
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场