https://leetcode-cn.com/problems/frog-jump/
思路一:记忆化搜索应该是比较直观的,就是给爆搜加了一个记忆化的优化,用
v
i
s
[
i
]
[
j
]
vis[i][j]
vis[i][j]记录在第
i
i
i块石子上跳
j
j
j步是否有解,然后就是比较常见的搜索写法了,不多赘述。
class Solution {
public:
vector<unordered_map<int,bool>> vis;
bool dfs(vector<int>& stones,int cur,int prejump)
{
auto it=lower_bound(stones.begin(),stones.end(),cur);
if(it==stones.end())
return false;
else if(*it!=cur)
return false;
else
{
if(*it==stones.back())
return true;
int idx=it-stones.begin();
bool flag=false;
for(int curjump=prejump-1;curjump<=prejump+1;curjump++)
{
if(curjump<=0)
continue;
auto it2=vis[idx].find(curjump);
if(it2==vis[idx].end())
{
vis[idx][curjump]=dfs(stones,cur+curjump,curjump);
flag=vis[idx][curjump];
}
else
flag=it2->second;
if(flag)
break;
}
return flag;
}
return false;
}
bool canCross(vector<int>& stones) {
vis.resize(stones.size());
return dfs(stones,stones[0],0);
}
};
思路二:进一步思考,基于题意不难知道青蛙在第
i
i
i个石块上最多跳
i
+
1
i+1
i+1步,接下来考虑动态规划,用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示上一次跳了
j
j
j步的情况下能否到达第
i
i
i个石块,那么可以写出转移方程:
d
i
s
=
s
t
o
n
e
s
[
i
]
−
s
t
o
n
e
s
[
j
]
,
0
<
=
j
<
i
&
&
d
i
s
<
=
j
+
1
dis=stones[i]-stones[j],0<=j<i\ \&\&\ dis<=j+1
dis=stones[i]−stones[j],0<=j<i && dis<=j+1
d
p
[
i
]
[
d
i
s
]
=
d
p
[
j
]
[
d
i
s
−
1
]
∣
∣
d
p
[
j
]
[
d
i
s
]
∣
∣
d
p
[
j
]
[
d
i
s
+
1
]
dp[i][dis]=dp[j][dis-1]||dp[j][dis]||dp[j][dis+1]
dp[i][dis]=dp[j][dis−1]∣∣dp[j][dis]∣∣dp[j][dis+1]
class Solution {
public:
bool canCross(vector<int>& stones) {
int n=stones.size();
for(int i=1;i<n;i++)
if(stones[i]-stones[i-1]>i)
return false;
vector<vector<bool>> dp(n,vector<bool>(n));
dp[0][0]=1;
for(int i=1;i<n;i++)
{
for(int j=i-1;j>=0;j--)
{
int dis=stones[i]-stones[j];
if(dis>j+1)
break;
dp[i][dis]=dp[j][dis-1]||dp[j][dis]||dp[j][dis+1];
if(i==n-1&&dp[i][dis])
return true;
}
}
return false;
}
};