尺取法


尺取法

尺取法核心思路

尺取法其實也是一種模擬,是解決尋找區間和問題的一種方法。

假如有這么一個問題:給你一些數,請在這些數中找到一個區間,使得區間里每一個元素的和大於或等於給定的某個值。

不會尺取法的話,肯定就會開雙重循環,枚舉區間起點和終點,然后每一次都求一次和,再和給定的數作比較。

尺取法與它的思路類似,都是尋找一個區間的起點和終點。做法是:

用兩個指針,最初都指向,這一組數中的第一個,然后如果這個區間的元素之和小於給定的數,就把右指針向右移,直到區間和大於等於給定的值為止。之后把左指針向右移,直到區間和等於給定的值為止,保存方案,繼續操作。

假如左指針指向這些數的第一個,並且右指針指向這組數的最后一個,這種情況下的子區間元素之和仍然小於給定的數的話,那么就輸出-1,表示不可能。

那么怎么求區間和呢?

當然,for一遍是可以的,但是太浪費時間了。我們可以引入一個累加器,初始值等於這組數中的第一個元素(因為最開始左指針和右指針都指向它),當右指針向右移時,累加器每次就加上右指針指向的元素的值。當左指針向右移時,累加器每次就減去左指針指向的值。

怎么實現呢?

實現

這里有道模板題

poj3061

下面附上代碼(不是我寫的)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int a[100000+33];
int ans,S,N;

void solve()
{
    ans=100000+44; 
    int L=1,R=1,sum=0,lsub=0;
    while(R<=N)
    {
        while(sum<S&&R<=N)//R總指向當前滿足要求區間的下一個 注意此處R可能>N 
        {
            sum+=a[R];//累加器加上右指針指向的元素
            ++R;//右指針向右移
            ++lsub;
        }
        while(sum>=S)//L總指向當前區間的最左邊  左閉右開 
        {
            sum-=a[L];//累加器減去左指針指向的元素的值
            ++L;//左指針右移
            --lsub;
        }
        ans=min(ans,lsub+1);
    }
}

int main()
{
    int T,i,sum;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&N,&S);
        sum=0; bool flag=false;
        for(i=1;i<=N;++i) 
        {
            scanf("%d",&a[i]);
            sum+=a[i];
            if(sum>=S&&!flag) flag=true;    
        }
        if(!flag)
        {
            printf("0\n"); continue;
        }
        solve();
        printf("%d\n",ans);
    }
    return 0;
}

尺取法嘛。。應該很好懂,就是一種模擬的策略。

寫在最后

wow!!!!!!!!!!!
這篇文章截止我看的時候已經有930閱讀量了!!!!!!!!
好雞凍!!!!!!!
感謝各位的支持!
errr。。。。
沒有別的意思,希望各位看了我文章的帶佬寫幾個評論唄。。。說個 寫得好!或者噴幾句我這只菜雞 也行啊QAQ
真的感謝你能看到這里!感謝你的支持!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM