版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luke2834/article/details/79478990
题意
n
个石头排成一行,i
-th石头所在位置是pos(i)
,假如青蛙目前在i
-th石头上,且它是从前面石头跳了k
单位长度过来的,则它接下来可以跳k + 1
,k - 1
,k
单位长度远,初始在0
位置,且只能跳1
单位长度,问它能否跳到最后一个石头。(n < 1100
)
思路
- 这个题我们最简单的dp思路,就是
dp(i, k)
表示在第i
个石头上,且从上一个石头跳k
单位长度过来,是否可行。但是由于k
每次可以加1
,它最大可以到O(n^2)
,复杂度过高 - 我们可以进一步简化dp,其实第
i
个石头必然是从前i-1
个石头上跳过来的,上一个定了,k
也就定了,所以k
的范围可以被缩小到O(n)
,状态定义就是dp(i, j)
表示在第i
个石头上,且从第j
个石头跳过来,是否可行 - 进一步,考虑
dp(i, j)
有效的可能不多,所以用一个hash set存储可行的方案,当然这步我也不确定是否可以加速,因为没有本质上降低复杂度,且hash set插入时开新内存空间可能慢一些。
实现
class Solution {
public:
bool canCross(vector<int>& stones) {
int n = stones.size();
unordered_map<int, int> mapp;
vector<unordered_set<int>> dp(n);
for (int i = 0; i < n; i++){
mapp[stones[i]] = i;
}
dp[0].insert(1);
for (int i = 0; i < n; i++){
for (auto it : dp[i]){
int d = it + stones[i];
if (mapp.find(d) != mapp.end()){
for (int j = 1; it + j > 0 && j >= -1; j--){
dp[mapp[d]].insert(it + j);
}
}
}
}
return dp[n-1].size();
}
};