毛毛虫算法
标签: 机试攻略 - 满分篇
学习人数: 16.4k


高清播放
赞赏支持

毛毛虫算法(官方称为尺取法)通常是指对数组保存一对下标(起点、终点),然后根据实际情况交替推进两个端点直到得出答案的方法,这种操作很像是毛毛虫(尺取虫)爬行的方式故得名。

 

Subsequence
题目描述:

给出了N个正整数(10 <N <100 000)的序列,每个正整数均小于或等于10000,并给出了一个正整数S(S <100 000 000)。 编写程序以查找序列中连续元素的子序列的最小长度,其总和大于或等于S。
输入描述:
第一行是测试用例的数量。 对于每个测试用例,程序必须从第一行读取数字N和S,并以一个间隔分隔开。 序列号在测试用例的第二行中给出,以间隔分隔。 输入将以文件结尾结束。
输出描述:
对于每种情况,程序都必须将结果打印在输出文件的单独一行上。如果没有答案,则打印0。
输入样例#:
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
输出样例#:
2
3
题目来源:
DreamJudge 1570

题目解析:这是一个典型的毛毛虫算法的应用实例,下面详细讲解一下算法过程。
我们设以as开始总和最初大于S时的连续子序列为as+...at-1,这时
as+1+...+at-2 < as+...+at-2 < S
所以从as+1开始总和最初超过S的连续子序列如果是as+1+...+at’-1的话,则必然有t<=t’。利用这一性质便可以设计出如下算法:
(1)以s = t = sum = 0初始化。
(2)只要依然有sum < S, 就不断将sum增加at,并将t增加1.
(3)如果(2)中无法满足sum >= S则终止。否则的话,更新res = min(res, t-s)。
(4)将sum减去as,s增加1然后回到(2)。

 

参考代码

#include<bits/stdc++.h>  
using namespace std;  
  
int a[100005];  
int main() {  
    int T, n, s;  
    scanf("%d", &T);  
    while(T--) {  
        scanf("%d%d", &n, &s);  
        for(int i = 1;i <= n;i++)  
            scanf("%d", &a[i]);  
        int l = 1,r = 1,sum = 0,ans = 0x3f3f3f3f;  
        while(1) {  
            while(sum < s && r <= n) sum += a[r++];  
            if(sum < s) break;  
            ans = min(ans, r-l);  
            sum -= a[l++];  
        }  
        if(ans == 0x3f3f3f3f) printf("0\n");  
        else printf("%d\n", ans);  
    }  
   ...
登录查看完整内容


课后作业

题目练习

DreamJudge 1591 逛画展


登录后开始许愿

暂无评论,来抢沙发