zoukankan      html  css  js  c++  java
  • 尺取法学习笔记

    今天老师讲了提了下尺取,于是就有了这篇笔记

    PS:我觉得我们老师形容得很贴切,尺取就像虫子蠕动一样

    例题:

    给出一个序列,求区间和大于或者等于S的最短区间长度.
    

    我们假设序列长度为10,S为15,序列为

    3 2 8 10 5 3 8 4 2 9
    

    尺取法的思路大概就是,我们使用三个变量L,R,tot, 表示区间的左右两边和区间权值和

    先初始L=R=1,tot=0

    然后开始蠕动

    过程:

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L: +
     R: +
    
    计算区间tot+=a[R] 再将R向前移动一位
    得出tot=3,比S小,所以我们将R向后移动

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L: +
     R:    +
    
    计算区间tot+=a[R] 再将R向前移动一位
    得出tot=5,比S小,继续移动R

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L: +
     R:       +
    
    计算区间tot+=a[R] 再将R向前移动一位
    得出tot=13,比S小,继续移动R

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L: +
     R:          +
    
    计算区间tot+=a[R] 再将R向前移动一位
    得出tot=13,比S小,继续移动R

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L: +
     R:             +
    
    计算区间tot+=a[R] 再将R向前移动一位
    得出tot=23,比S大,停止移动R,记录当前区间长度K=4

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L:    +
     R:             +
    
    因为R已经不能再移动,因此我们移动L
    计算区间tot-=a[L] 再将L向前移动一位,因为原本L所在位置已经不属于这个区间了
    得出tot=20,比S大,R继续不动,记录当前区间长度K=3

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L:       +
     R:             +
    
    计算区间tot-=a[L] 再将L向前移动一位
    得出tot=18,比S大,R继续不动,记录当前区间长度K=2

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L:          +
     R:             +
    
    计算区间tot-=a[L] 再将L向前移动一位
    得出tot=10,比S小,重新移动R

     i: 1  2  3  4  5  6  7  8  9  10
    ai: 3  2  8  10 5  3  8  4  2  9
     L:          +
     R:                +
    
    计算区间tot+=a[R] 再将R向前移动一位
    得出tot=15,等于S,R不动,移动L,记录区间长度K=2

    以下过程省略...

    观察这个过程,这就是尺取法了,如果把L看做虫的尾巴,R看做虫的头,那么完全就是一个蠕动的过程:

    L_/\_R
    先向右延伸区间
    L_____R
     到达边界后向左缩小区间
     L_/\_R
      
     L_____R
      
      L_/\_R
       
       L_____R
    

    以下是毒瘤代码实现:

    #include<bits/stdc++.h>
    #define RE register
    #define IOS ios::sync_with_stdio(false)
    #define (x) [x]
    #define cin(x) cin>>x
    #define cout(x) cout<<x
    #define Endl puts(" ")
    #define Ww(i,j) while(i<=j)
    #define WW(i1,j1,i2,j2) while(i1<j1&&i2<j2)
    #define B break;
    #define Length(l,r) r-l+1
    #define MMIINN(a,b) a<=b?a:b
    #define INF 2147483647
    #define F(s,j) for(int i=s;i<=j;++i)
    #define R return
    #define I(i,j) if(i<j)
    using namespace std;
    int S,n,a[1000001],l=1,r=0,now=0,ans=INF;
    int main (){
        IOS;
        cin(n),cin(S);
        F(1,n)
    		cin(a(i));
    	Ww(l,n){
    		WW(now,S,r,n) now+=a(++r);
    		I(now,S) B;
    		ans=MMIINN(ans,Length(l,r)); 
    		now-=a(l++);
    	}
    	cout(ans);
    	Endl;
    	R 0;
    }
    
  • 相关阅读:
    sprintf使用
    Android ListView保持选中项高亮
    Creational Patterns创建型模式
    C和指针终于看到指针这一章
    C++随笔001
    TCP reset
    开始看设计模式英文版了
    Excel条件求和
    linux中安装软件,查看、卸载已安装软件方法
    linux vi文本编辑器三种模式切换及常用操作
  • 原文地址:https://www.cnblogs.com/IQZ-HUCSr-TOE/p/12631082.html
Copyright © 2011-2022 走看看