LeetCode 5331
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 \rightarrow 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;
}
};