题目如下
小明冒充 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