挑战3.2.1 Subsequence (poj 3061)

来源:互联网 发布:学乐器的软件 编辑:程序博客网 时间:2024/06/05 05:22

题目描述

尺取法

这里写图片描述

简(mang)单(mu)分析


给了一串数,找一个子串使得他们的和大于给定的数S。复杂的方法这里就不多说了,介绍一下尺取法。

  • 基本思想
    通过首位缩小区间的长度来求解最小的那个长度

  • 具体步骤
    给定s, t来表示首尾的一个指针。sum表示当前区间的和,res记录最短的长度。
    1.将s=t=sum初始化0
    2.只要sum < S,就将t指针向后移,并把S加上后面的一个数。(当sum>S停止)
    3.(此时的sum满足条件,但是长度不一定最小)将sum减去最前面的一个数,s向后移动一个。
    4.当sum< S时退出循环(本来在操作2的时候应该大于S的,小于S表示从s开始到最后一个数都加上还是不能满足sum大于S,就没有必要继续操作3了)

  • 代码

#include <iostream>using namespace std;int min(int a, int b){    return a < b ? a : b;}int main(){    int test;    cin >> test;    while (test--)    {        int n, s;        cin >> n >> s;        int num[100005] = { 0 };        for (int i = 0; i < n; i++)            cin >> num[i];        long long int res = n + 1, j = 0, i = 0;        long long int sum = 0;        while (1)        {            while (sum < s&&j < n)                sum += num[j++];            if (sum < s) break;            res = min(res, j - i);            sum -= num[i++];        }        if (res>n) cout<<0<<endl;        else cout<<res<<endl;    }    return 0;}

实际这题也相当于是一种dp,dp[i]表示从i开始向后加和刚好大于S的最小长度,但是当i>某个数的时候即使加到了最后一个数也不一定满足大于S这个条件。因此上面只要在执行了1以后还不能满足就可以退出这个大循环了

原创粉丝点击