问题描述
小蓝有一天误入了一个混境之地。
好消息是:他误打误撞拿到了一张地图,并从中获取到以下信息:
- 混境之地是一个 n⋅mn⋅m 大小的矩阵,其中第 ii 行第 jj 列的的点 hijhij 表示第 ii 行第 jj 列的高度。
- 他现在所在位置的坐标为 (A,B)(A,B) ,而这个混境之地出口的坐标为 (C,D)(C,D) ,当站在出口时即表示可以逃离混境之地。
- 小蓝有一个喷气背包,使用时,可以原地升高 kk 个单位高度。
坏消息是:
- 由于小蓝的体力透支,所以只可以往低于当前高度的方向走。
- 喷漆背包燃料不足,只可以最后使用一次。
小蓝可以往上下左右四个方向行走,不消耗能量。
小蓝想知道他能否逃离这个混境之地,如果可以逃离这里,输入 Yes
,反之输出 No
。
输入格式
第 11 行输入三个正整数 n,mn,m 和 kk , n,mn,m 表示混境之地的大小, kk 表示使用一次喷气背包可以升高的高度。
第 22 行输入四个正整数 A,B,C,DA,B,C,D ,表示小蓝当前所在位置的坐标,以及混境之地出口的坐标。
第 33 行至第 n+2n+2 行,每行 mm 个整数,表示混境之地不同位置的高度。
输出格式
输出数据共一行一个字符串:
- 若小蓝可以逃离混境之地,则输出
Yes
。 - 若小蓝无法逃离混境之地,则输出
No
。
样例输入1
5 5 30
1 1 5 5
3 20 13 12 11
19 17 33 72 10
12 23 12 23 9
21 43 23 12 2
21 34 23 12 1
样例输出1
Yes
样例解释1
从 (1,1)(1,1) 到 (5,5)(5,5) 的一条可行道路为:
- 在 (1,1)(1,1) 处使用喷气背包。
- (1,1)−>(1,2)−>(1,3)−>(1,4)−>(1,5)−>(2,5)−>(3,5)−>(4,5)−>(5,5)(1,1)−>(1,2)−>(1,3)−>(1,4)−>(1,5)−>(2,5)−>(3,5)−>(4,5)−>(5,5) 。
样例输入2
5 5 10
1 1 5 5
3 2 13 12 11
1 17 33 72 10
12 23 12 23 9
21 43 23 12 2
21 34 23 12 1
样例输出2
No
样例解释2
可以证明不存在一条路径可以从起点到达终点。
数据范围
对于所有测试样例, 1≤n,m≤10001≤n,m≤1000 , 1≤k,hij≤1061≤k,hij≤106 。
运行限制
语言 | 最大运行时间 | 最大运行内存 |
---|---|---|
C++ | 1s | 512M |
C | 1s | 512M |
Java | 2s | 512M |
Python3 | 3s | 512M |
PyPy3 | 3s | 512M |
Go | 3s | 512M |
JavaScript | 3s | 512M |
代码
记忆化搜索,记忆化搜索体现(个人见解 当新坐标可以达到那么 现在这个坐标也可以到达,就记到了,如果新坐标四个方向上,不管是喷气,还是往低的方向走都不可达到那么说明真的就达到不了了)
from functools import lru_cache
@lru_cache(maxsize=None)
def dfs(x,y,z):
##x 横坐标
##y 纵坐标
##z 是否使用了喷气包
if x==C and y==D:
## 递归的出口是走到了C,走到了D
return True
## 对于在每个点是怎么做的呢 是为了走到C,D,要么消耗喷气包要么不消耗喷气包
## 对于每一次可以向上下左右四个方向走
delta=[(0,-1),(0,1),(-1,0),(1,0)]
## 对于每个方向迭代一下
for delta_x,delta_y in delta:
xx,yy=x+delta_x,y+delta_y
## n行m列 因此横坐标限制为n纵坐标限制为m
if xx<0 or xx>=n or yy<0 or yy>=m:
## 如果发生了越界那么就跳过
continue
## 新坐标比旧坐标低那么就可以走到新坐标
if Map[xx][yy]<Map[x][y]:
## 往低于当前高度的地方走
if dfs(xx,yy,z):
## 新坐标走到终点这里也可以走到终点
return True
## 没有使用喷气z不变,可以使用
##
elif z==False and Map[xx][yy]<=Map[x][y]+k:
## 新坐标比旧坐标高,但是新坐标比旧坐标+喷气高度低
if dfs(xx,yy,True):
## 新坐标走到终点这里也可以走到终点
return True
## for循环是探究一种情况 里面返回的是True False探究的是另一种情况,应该是和for并列的
return False
n,m,k=map(int,input().split())
A,B,C,D=map(int,input().split())
A,B,C,D=A-1,B-1,C-1,D-1
##这里的Map是从0开始的
Map=[]
for i in range(n):
Map.append(list(map(int,input().split())))
##dfs(0,0,False)
if dfs(A,B,False):
print('Yes')
else:
print('No')