[leetcode] 798 得分最高的最小轮调 - 思维dp

Posted PushyTao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[leetcode] 798 得分最高的最小轮调 - 思维dp相关的知识,希望对你有一定的参考价值。

题目链接

轮调实际上是这个样子的:
每次讲最前面的元素放到数组最后,然后将所有元素集体向前移动一位
在当前值 a [ i ] ≤ i a[i] \\leq i a[i]i的时候会获得 1 1 1分,问最大的的分是多少?
先说明一个事实:
一次轮调之后,对于除了最前面的每个数,他的下标会减小 1 1 1,而对于最前面的那个数,他的下标直接变为最大
大致分为以下三种情况:

  1. 本来 a [ i ] a[i] a[i]就小于下标 i i i,轮调之后下标减小值不变,所以依旧会获得 1 1 1
  2. 本来 a [ i ] = = i a[i] == i a[i]==i,轮调之后,下标减小而值不变,所以值就比下标大 1 1 1,所以说会失去 1 1 1
  3. 本来 a [ i ] > i a[i] > i a[i]>i,轮调之后,下标更小,值依旧会大于下标,所以依旧不得分
  4. 在最前面的数,一次轮调之后,被放到最大的下标的位置,会得到 1 1 1

我们用 d p [ i ] dp[i] dp[i]表示在第 i i i次轮调之后会得到的分数,那么就有:
d p [ i ] = d p [ i − 1 ] − x + 1 dp[i] = dp[i-1] - x + 1 dp[i]=dp[i1]x+1
其中, x x x表示 i − 1 i-1 i1次轮调时下标和值相等的个数
在这里 x x x可以预处理得到

式中的 + 1 + 1 +1是为了解决数组最前面的数到数组最后的最大下标处的贡献值
d p [ 0 ] = 未 轮 调 的 时 候 的 得 分 dp[0] = 未轮调的时候的得分 dp[0]=
因为之和前一个关系有关,所以我们可以只用一个变量解决,记录最大值处的下标返回即可

Code:

class Solution 
public:
    int bestRotation(vector<int>& nums) 
        int val = 0;
        const int n = nums.size();
        int a[n+1],pos = 0;
        memset(a,0,sizeof a);
        for(int i = 0; i < n;i ++) 
            if(nums[i] <= i) val ++;
        
        int mxval = val;
        for(int i = 0; i < n;i ++) 
            if(i >= nums[i]) a[i-nums[i]] ++;
            else a[i + n - nums[i]] ++;
        
        
        for(int i=1;i<n;i++) 
            val = val - a[i-1] + 1;
            if(val > mxval) 
                val = mxval;
                pos = i;
            
        
        return pos;
    
;

以上是关于[leetcode] 798 得分最高的最小轮调 - 思维dp的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 1255. 得分最高的单词集合

LeetCode 1255. 得分最高的单词集合

LeetCode 1255 得分最高的单词集合状态压缩 位运算HERODING的LeetCode之路

LeetCode 5258. 得分最高的单词集合 Maximum Score Words Formed by Letters

LeetCode 2155. 分组得分最高的所有下标

1102. 得分最高的路径