题目链接
题目大意
一只青蛙想要过河。 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有)。 青蛙可以跳上石子,但是不可以跳入水中。
给你石子的位置列表
s
t
o
n
e
s
stones
stones(用单元格序号 升序 表示), 请判定青蛙能否成功过河(即能否在最后一步跳至最后一块石子上)。
开始时, 青蛙默认已站在第一块石子上,并可以假定它第一步只能跳跃一个单位(即只能从单元格
1
1
1 跳至单元格
2
2
2 )。
如果青蛙上一步跳跃了
k
k
k 个单位,那么它接下来的跳跃距离只能选择为
k
−
1
k - 1
k−1、
k
k
k 或
k
+
1
k + 1
k+1 个单位。 另请注意,青蛙只能向前方(终点的方向)跳跃。
示例 1
输入:stones = [0,1,3,5,6,8,12,17]
输出:true
解释:青蛙可以成功过河,按照如下方案跳跃:跳 1 个单位到第 2 块石子, 然后
跳 2 个单位到第 3 块石子, 接着 跳 2 个单位到第 4 块石子, 然后跳 3 个单位
到第 6 块石子, 跳 4 个单位到第 7 块石子, 最后,跳 5 个单位到第 8 个石子
(即最后一块石子)。
示例 2
输入:stones = [0,1,2,3,4,8,9,11]
输出:false
解释:这是因为第 5 和第 6 个石子之间的间距太大,没有可选的方案供青蛙跳跃
过去。
提示:
2
≤
s
t
o
n
e
s
.
l
e
n
g
t
h
≤
2000
2 \leq stones.length \leq 2000
2≤stones.length≤2000
0
≤
s
t
o
n
e
s
[
i
]
≤
2
31
−
1
0 \leq stones[i] \leq 2^{31} - 1
0≤stones[i]≤231−1
s
t
o
n
e
s
[
0
]
=
=
0
stones[0] == 0
stones[0]==0
记忆化搜索+动态规划
f
[
i
]
[
j
]
f[i][j]
f[i][j]:表示在第
i
i
i 个点,往后跳
j
j
j 个单位的情况。
第 0 个位置到第 1 个 位置跳 1
第 1 个位置到第 2 个 位置可以跳 1,2
第 2 个位置到第 3 个 位置可以跳 1,2,3
...
第 n - 1 个位置到第 n 个位置可以跳 1,2,3 ... n - 1,n
写个记忆化搜索记录状态,判断一下是否有满足的即可。
const int maxn = 2e3 + 7;
int dp[maxn][maxn];
class Solution {
public:
unordered_map<int,int>hash;
vector<int> p;
int dfs(int x, int k)
{
if(dp[x][k] != -1) return dp[x][k];
dp[x][k] = 0;
for(int i = max(1,k-1); i <= k + 1; i++)
{
int t = p[x] - i;
if(hash.count(t) && dfs(hash[t],i))
{
dp[x][k] = 1;
break;
}
}
return dp[x][k];
}
bool canCross(vector<int>& stones) {
p = stones;
int len = p.size();
for(int i = 0; i < len; i++) hash[p[i]] = i;
memset(dp, - 1, sizeof dp);
dp[0][1] = 1;
for(int i = 1; i <= len; i++)
if(dfs(len-1,i)) return true;
return false;
}
};