zoukankan      html  css  js  c++  java
  • 尺取详解 (Subsequence)

    有这么一类问题,需要在给的一组数据中找到不大于某一个上限的“最优连续子序列”

    于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式比较流行的叫法是“尺取法”。

    Poj3061     

    给长度为n的数组和一个整数m,求总和不小于m的连续子序列的最小长度

    输入

    n = 10,m = 15

    5 1 3 5 10 7 4 9 2 8

    输出

    2

    那么我们先用sum存当前这个子序列的和,从左边第一个数来存,直到这个子序列的和大于等于m为止,再记录下当前长度。

    其实相当于当不满足条件就入队,然后得到队列长度,再将队首元素出队,再进行下一次的入队,直到满足条件再次出队,并且将这一次的长度与历史最短长度进行取舍,最后扫到最后的元素却无法再满足入队条件的时候就结束,此时用O(n)的时间就可以得到答案。

    如下,我把样例用毛毛虫爬一遍,红色的是当前“毛毛虫着地”也就是刚好满足题意的子序列的地方:

    5 1 3 5 10 7 4 9 2 8

    1 3 5 10 7 4 9 2 8

    5 1 3 5 10 7 4 9 2 8

    5 1 3 5 10 7 4 9 2 8

    5 1 3 5 10 7 4 9 2 8

    5 1 3 5 10 7 4 9 2 8

    5 1 3 5 10 7 4 9 2 8

    5 1 3 5 10 7 4 9 2 8

    5 1 3 5 10 7 4 9 2 8

      以上转自   http://blog.chinaunix.net/uid-24922718-id-4848418.html

    A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.

    Input

    The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.

    Output

    For each the case the program has to print the result on separate line of the output file.if no answer, print 0.

    Sample Input

    2
    10 15
    5 1 3 5 10 7 4 9 2 8
    5 11
    1 2 3 4 5

    Sample Output

    2
    3

    给出了n个正整数序列(10<n<100,000),它们均小于或等于10000,正整数s(s<100 000 000)。编写一个程序来查找序列的连续元素的子序列的最小长度,其总和大于或等于S。

    输入

    第一行是测试用例的数量。对于每个测试用例,程序必须从第一行读取由间隔分隔的数字n和s。序列的数目在测试用例的第二行中给出,由间隔分隔。输入将以文件结尾完成。

    产量

    对于每种情况,程序都必须在输出文件的单独行上打印结果。如果没有答案,请打印0。

    思路

    那么我们先用sum存当前这个子序列的和,从左边第一个数来存,直到这个子序列的和大于等于m为止,然后从这个子序列的头开始减,减到小于s为止,每当子序列改变并且sum大于s时,就记算长度于min比较,取最小。

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            long long n,s,a[1000100];
            scanf("%lld %lld",&n,&s);
            int i,k,j;
            for(i=0;i<n;i++)
                scanf("%lld",&a[i]);
            long long st,en,sum=0;
            long long minn=1e9;
            st=0;en=0;
            for(;;)
            {
                sum+=a[en];
                while(sum>=s)
                {
                    long long t=en-st+1;
                    if(t<minn)
                        minn=t;
                    st++;
                    sum-=a[st-1];
                }
                en++;
                if(en==n)
                    break;
            }
            if(minn==1e9)
                minn=0;
            printf("%lld
    ",minn);
        }
        return 0;
    }

    另一道非常好的题:https://blog.csdn.net/Septembre_/article/details/81086868

  • 相关阅读:
    vue 将毫秒转为日期
    element-ui 点击获取table的行索引
    LInux设置tomcat端口为80
    java引用传递和值传递
    java包装类的自动装箱及缓存
    理解JVM之java内存模型
    理解JVM之类加载机制
    理解JVM之内存分配以及分代思想实现
    理解JVM之垃圾回收
    理解JVM之对象的生命周期
  • 原文地址:https://www.cnblogs.com/jk17211764/p/9677403.html
Copyright © 2011-2022 走看看