leetcode 周赛271记录-Maximum Fruits Harvested After at Most K Steps

该博客探讨了一种寻找最优解的策略,用于在给定步数限制下最大化收集水果的数量。核心思想是通过确定最优路径(先左后右或先右后左,最多转向一次)并利用前缀和计算区间内的水果总数。通过对x和y的搜索,找到使区间水果数量最大的x值,并考虑两种不同路径情况分别进行计算。最终通过比较两种策略的结果,得出全局最优解。实现过程中,维护数轴前缀和能有效提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述在这里插入图片描述

  • 基本思想:找出最优解所满足的形式(即必要条件),然后在这样的条件下通过搜索的方式找出最优解
  • 首先,最优路径一定是先向左走到头(这里的头指的是最优解的边界),然后再向右走到头,最多转向一次,或者先向右走到头,然后再向左走到头,最多转向一次
  • 设原点为startPosstartPosstartPos,以原点向左走的最大步数为xxx,以原点向右走的最大步数为yyy

当采用前一种做法时原问题为:

[startpos−x,startpos+y][startpos - x,startpos +y][startposx,startpos+y]区间内水果的最大数目,在满足约束条件2x+y≤k2x + y \leq k2x+ykx≤yx \leq yxy的条件下。

  • 在给定xxx的条件下,要使得区间尽量大,显然有y=k−2xy = k - 2xy=k2x
  • 并且x≤yx \leq yxy,否则可以使用后一种做法(先向右走到尽头,再向左走到尽头)而使得步数k还没有用尽

原问题转换为:求得一个大于等于0得正整数xxx使得区间[startpos−x,startpos+k−2x][startpos - x,startpos + k - 2x][startposx,startpos+k2x]中水果数目达到最大值。

  • 并且需要满足k−2x≥0,x≥0,3x≤kk - 2x \geq 0,x \geq 0,3x \leq kk2x0,x03xk,由于第一个不等式必须成立,且注意到整数,因此约束条件为0≤x≤⌊k/3⌋0\leq x \leq \lfloor k/3 \rfloor0xk/3
  • 在这个区间上执行搜索xxx,找到最优的xxx对应的值即可得到结果。
    • 可在最大数据范围内维护数轴的前缀和即可实现,pre[i]表示截止i位置的pre[i]表示截止i位置的pre[i]i所有水果个数。欲求任意区间的数值可直接用两个前缀和详见即可

当采用后一种做法时原问题为:
[startpos−x,startpos+y][startpos - x,startpos +y][startposx,startpos+y]区间内水果的最大数目,在满足约束条件x+2y≤kx + 2y \leq kx+2ykx>=yx >=yx>=y的条件下。

  • 即: 求[startpos−k+2y,startpos+y][startpos - k + 2y,startpos +y][startposk+2y,startpos+y]区间内水果的最大数目,在满足约束条件 0≤y<=⌊k/3⌋0\leq y<= \lfloor k/3\rfloor0y<=k/3的条件下
class Solution {
    public int maxTotalFruits(int[][] fruits, int startPos, int k) {
        int[] pre = new int[200001];   //保存前缀和
        //统计前缀和
        int i ;
        int next ;
        if(fruits[0][0] == 0)
        {
            pre[0] = fruits[0][1];
            next = 1;
        }
        else
        {
            pre[0] = next = 0;
        }
        for(i = 1;i<pre.length && next < fruits.length;i++)
        {
            if(i == fruits[next][0])
            {
                pre[i] = pre[i - 1] + fruits[next][1];
                next++;
            }
            else pre[i] = pre[i - 1];
        }
        for(;i<pre.length;i++)
            pre[i] = pre[i - 1];
        int ans = 0;
        for(int x = 0;x<=k/3;x++)
        {
            int lower = startPos - x <=0?0:pre[startPos - x - 1];
            int upper = startPos + k - 2*x >= 200000?pre[200000] : pre[startPos + k - 2*x];
            ans = Math.max(ans,upper - lower);
        }
        for(int y = 0;y<=k/3;y++)
        {
            int lower = startPos - k + 2*y<=0?0:pre[startPos - k + 2*y - 1];
            int upper = startPos + y>=200000?pre[200000]:pre[startPos + y];
            ans = Math.max(ans,upper - lower);
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值