解题思路:
作为困难题本质其实一点也不困难,用动态规划的方法其实就是构建二维的dp方程。首先构建状态转移方程,dp[i][k] 表示到达i位置石头之前跳过了k个石头,dp[i][k] = dp[j][k - 1] || dp[j][k] || dp[j][k + 1];每次到达i位置且之前跳过k个石头是通过三种情况进行判断的,优化的方法需要仔细观察,就是两个石头之间的聚类如果超过了下标那么肯定就跳过不过去,这可以用最远情况进行模拟,代码如下:
未优化代码
class Solution {
public:
bool canCross(vector<int>& stones) {
int len = stones.size();
// dp[i][k] 到达i位置石头之前跳过了k个石头
vector<vector<bool>> dp(len,vector<bool>(len));
dp[0][0] = true;
for(int i = 1; i < len; i ++) {
for(int j = i - 1; j >= 0; j --) {
int k = stones[i] - stones[j];
// 两个石头时间距离超过下标就不可能跨过去
if(k > j + 1) {
break;
}
// 注意这里每次到达i位置且之前跳过k个石头是通过三种情况进行判断的
dp[i][k] = dp[j][k - 1] || dp[j][k] || dp[j][k + 1];
// 如果到达终点且可以跳到
if(i == len - 1 && dp[i][k]) {
return true;
}
}
}
return false;
}
};
优化后代码
class Solution {
public:
bool canCross(vector<int>& stones) {
int len = stones.size();
// dp[i][k] 到达i位置石头之前跳过了k个石头
vector<vector<bool>> dp(len,vector<bool>(len));
dp[0][0] = true;
// 两个石头之间距离超过下标就不可能跨过去
for(int i = 1; i < len; i ++) {
if(stones[i] - stones[i - 1] > i) {
return false;
}
}
for(int i = 1; i < len; i ++) {
for(int j = i - 1; j >= 0; j --) {
int k = stones[i] - stones[j];
// 两个石头之间距离超过下标就不可能跨过去
if(k > j + 1) {
break;
}
// 注意这里每次到达i位置且之前跳过k个石头是通过三种情况进行判断的
dp[i][k] = dp[j][k - 1] || dp[j][k] || dp[j][k + 1];
// 如果到达终点且可以跳到
if(i == len - 1 && dp[i][k]) {
return true;
}
}
}
return false;
}
};