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

划分集合:

扫描二维码关注公众号,回复: 9100243 查看本文章

\(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;
    }
};

猜你喜欢

转载自www.cnblogs.com/strategist-614/p/12298735.html