算法之尺取

何为尺取

尺取法,便是形如用一把尺子的方法,一步一步去截取目标序列,最终满足一定的限制。
我个人理解更偏向于,尺取算法就像毛毛虫一样,有伸缩也有前进,在目标序列的一小节上进行操作(对左右节点操作等),使运行时间比单纯暴力少的多。

举个栗子

讲理论可能不太清楚,下面是一个尺取法的题目。

描述

冬日里的一抹暖阳总是能给人们留下深刻的记忆,人们喜爱冬天的太阳,就跟人们喜爱冬天的火锅一般。寒冷的冬天总会让人想起火锅,最近小Z特别想去吃火锅,刚好某家转转火锅刚开业有活动,有n盘火锅围成一个圈,第一盘和最后一盘是相连的,每一盘火锅都有一个价值a[i],现在可以吃连续的m盘火锅,小Z想知道他所吃的那连续的m盘火锅的最大价值可以是多少?你能帮帮憨憨的小Z吗。

格式
输入格式

第一行数入两个整数n,m(1<=m<=n<=2000000),分别表示火锅的盘数和可以吃的连续的盘数,第二行输入n的数ai,分别表示每一盘火锅的价值。

输出格式

输出一个整数,表示连续m盘火锅的最大价值。

样例
样例输入

5 3
6 1 2 5 3

样例输出

14

这个题目用暴力法可以每m个累加求和,求出最大,但是这需要运算多次,同时这个题n的数据比较大,暴力肯定不行。

用尺取解决这个问题的思路是:
我们已知尺子长度为m,我们便求出前m个火锅的价值和为sum,设左端点为0,右端点为m,不断移动尺子,同时比较交换与sum的大小,即可求解。

Tip

此题因为是个环,可以用一个while控制右端点小于n的,一个控制右端点超过n的。

下面为代码

#include <stdio.h>
int a[2000010];
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        int i;
        for(i=0; i<n; i++)
            scanf("%d",&a[i]);
        long long int sum=0;//此处用longlongint,和范围会超过int
        for(i=0; i<m; i++)
            sum+=a[i];
        long long int temp=sum;
        int l=0,r=m;
        while(r<n)
        {
            temp-=a[l];
            l++;
            temp+=a[r];
            r++;
            if(temp>sum)
                sum=temp;
        }
        r=0;
        while(l<n-1)
        {
            temp-=a[l];
            l++;
            temp+=a[r];
            r++;
            if(temp>sum)
                sum=temp;
        }
        printf("%lld\n",sum);
    }
}

总结:尺取法我认为是一种对尺子进行操作的方法,你求得第一个尺子后(既找到第一个满足条件的区间),在根据题目的限制条件,求得解答的方法,时间明显要比暴力求法短的多。

注意事项

必须清楚后续确定所要求解的区间如何进一步得到根据其端点得到,否则无法使用尺分法,一定需要注意问题的分析。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值