题目如下
小明冒充 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)]2014fcnty = [0 for _ in range(21)]# 记录箭的数量maps = [[False for _ in range(21)]for _ in range(21)]# 用于判断是否走过sun = Falsetot = 0# 箭的总数def check():# 判断是否完成,如果有一个为零,就不能往下走了for i in range(0, n):if cntx[i] != 0 or cnty[i] != 0:return Falsereturn Truedef dfs(x, y, num):global sunpath[num] = y *n + x # 坐标点maps[x][y] = Truecntx[x] -= 1 # 我们这步走过来拔剑cnty[y] -= 1 # 我们这步走过拔剑if x == n and y == n and check():sun = True# 完成走了returnfor 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] += 1cnty[y1] += 1n = 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])# 走了箭的一半的数量应该没毛病