5331
给你一个整数数组 (arr) 和一个整数 (d) 。每一步你可以从下标 i 跳到:
-
(i + x) ,其中 (i + x < arr.length) 且 (0 < x <= d)。
-
(i - x) ,其中 (i - x >= 0) 且 (0 < x <= d) 。
除此以外,你从下标 i 跳到下标 j 需要满足:(arr[i] > arr[j] 且 arr[i] > arr[k]) ,其中下标 (k) 是所有 (i) 到 (j) 之间的数字(更正式的,(min(i, j) < k < max(i, j)))。
你可以选择数组的任意下标开始跳跃。请你返回你 最多 可以访问多少个下标
请注意,任何时刻你都不能跳到数组的外面。
DP
集合 dp
分析法:
集合:从 (i) 出发能够到达的下标数量的集合
属性:max
划分集合:
(i - d leq j leq i + d) dp[j]
表示从 (j) 出发能到达的下标数量的集合 ((i
ightarrow j))
考虑 last
情况。
dp[j] = 1 + max(dp[j])
同时要满足能够从 (i) 到 (j) 的条件 : (arr[j] < arr[i])
同时这样的状态转移方程不是对状态递推的,有可能在计算 i
时,dp[(i+1)~(i+d)]
没有计算出,因此要先对 arr[i]
排序,保证在计算 i
时比它小的值已经计算出了。
#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
int dp[1005];
struct rec
{
int id;
int len;
friend bool operator<(const rec &a,const rec &b){
return a.len < b.len;
}
}a[1005];
int maxJumps(vector<int>& arr, int d) {
int n = arr.size();
for(int i =0;i < n;i++)
{
a[i].id = i;
a[i].len = arr[i];
}
sort(a ,a + n);
for(int i =0;i < n;i++)
{
int pos = a[i].id;
dp[pos] = 1;
for(int j = pos - 1;j >= 0 && j >= pos - d;j--)
{
if(arr[j] >= arr[pos]) break;//条件判断arr[j] < arr[i]
if(dp[j]) dp[pos] = max(dp[pos],dp[j] + 1);//状态转移方程
}
for(int j = pos + 1;j <= n - 1 && j <= pos + d;j++)
{
if(arr[j] >= arr[pos]) break;//条件判断arr[j] < arr[i]
if(dp[j]) dp[pos] = max(dp[pos],dp[j] + 1);
}
}
int ans = 1;
for(int i =0;i < n;i++) ans = max(ans,dp[i]);
return ans;
}
};