题目来源
青蛙跳的题目,河中有一堆石头,问青蛙能不能跳过河。
我一开始想着深度搜索遍历,代码如下:
class Solution {
public:
bool canCross(vector<int>& stones) {
unordered_set<int> sets;
for (auto stone : stones)
sets.insert(stone);
return dfs(0, 1, sets, stones.back());
}
bool dfs(int cur, int jump, unordered_set<int>& sets, int des)
{
if (jump == 0)
return false;
cur += jump;
if (cur == des)
return true;
if (sets.count(cur) == 0)
return false;
if (dfs(cur, jump-1, sets, des) || dfs(cur, jump, sets, des)
|| dfs(cur, jump+1, sets, des))
return true;
return false;
}
};
没错…有超时了…
然后想了想,应该是DP,存储一下某个位置某个jump能不能到达,代码如下:
class Solution {
public:
bool canCross(vector<int>& stones) {
unordered_set<int> sets;
for (auto stone : stones)
sets.insert(stone);
map<pair<int, int>, bool> canReach;
return dfs(0, 1, sets, stones.back(), canReach);
}
bool dfs(int cur, int jump, unordered_set<int>& sets, int des, map<pair<int, int>, bool>& canReach)
{
if (canReach.count(make_pair(cur, jump)) != 0)
return canReach[make_pair(cur, jump)];
if (jump == 0)
return false;
cur += jump;
if (cur == des)
return true;
if (sets.count(cur) == 0)
return false;
if (dfs(cur, jump-1, sets, des, canReach) || dfs(cur, jump, sets, des, canReach)
|| dfs(cur, jump+1, sets, des, canReach)) {
canReach[make_pair(cur, jump)] = true;
return true;
}
canReach[make_pair(cur, jump)] = false;
return false;
}
};
然后AC了,感觉爽爽的。不过看了下运行时间,还是比较慢的…
简洁很多的代码,本质上和我的做法是一样的,不过我是把每个都试过,而这个解法是只试石头位置,所以可以剪掉很多
代码如下:
class Solution {
public:
bool canCross(vector<int>& stones) {
map<pair<int, int>, bool> dp;
return canCross(stones, 0, 0, dp);
}
bool canCross(vector<int>& stones, int pos, int k, map<pair<int, int>, bool>& dp)
{
if (dp.count(make_pair(pos, k)) != 0)
return dp[make_pair(pos, k)];
for (int i=pos+1; i<stones.size(); i++) {
int gap = stones[i] - stones[pos];
if (gap < k - 1) continue;
if (gap > k + 1) {
dp[make_pair(pos, k)] = false;
return false;
}
if (canCross(stones, i, gap, dp)) return dp[make_pair(pos, k)] = true;
}
return pos == stones.size() - 1;
}
};