尺取法 poj3061

尺取法解决的问题在求区间的问题上,下面一段话摘抄自一个博客

尺取法通常适用于选取区间有一定规律,或者说所选取的区间有一定的变化趋势的情况,通俗地说,在对所选取区间进行判断之后,我们可以明确如何进一步有方向地推进区间端点以求解满足条件的区间,如果已经判断了目前所选取的区间,但却无法确定所要求解的区间如何进一步
得到根据其端点得到,那么尺取法便是不可行的。首先,明确题目所需要求解的量之后,区间左右端点一般从最整个数组的起点开始,之后判断区间是否符合条件在根据实际情况变化区间的端点求解答案。

以POJ 3061为例了解一下尺取法的用途吧

Language:
Subsequence
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 17154 Accepted: 7293
Description

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个数里找一段区间和大于等于s,并且最小化这个区间的长度
假设有两个游标,x1,x2 ,让x2不断的向右移并在这个过程当中求和,当遇到sum>=s的情况下,停止游标x2的移动,然后移动左游标x1缩减区间,在这个过程当中。如果在移动的过程中已经x2已经到了末尾且此时sum仍小于s,结束枚举。

import java.util.*;
public class Main{
        public static int maxn = (int)(1e6);
         public static int[] sum = new int[maxn+10];
         public static int[] a = new int[maxn+10];
     public static void main(String []args){
         Scanner scanner = new Scanner(System.in);
         int T,n,s,ans;
         T = scanner.nextInt();
        while((T--)!=0){
            n = scanner.nextInt();
            s = scanner.nextInt();
            sum[0]=0;
            for(int i=1;i<=n;i++){
                a[i] = scanner.nextInt();
                sum[i]=sum[i-1]+a[i];
            }
            int left=1,right=1;
             ans = n+1;
          while(1!=2){
              while(right<=n&&(sum[right]-sum[left-1]<=s)){
                  right++;
              }
              if(right>n){
                  break;
              }
              ans = Math.min(ans,right-left+1);
              left++;
          }
          if(ans!=(n+1))
          System.out.println(ans);
         else
          System.out.println(0);
          
     }
}
}

笔记:
数组一般开到 1e6+10即可最大值
java定义le6的maxn
public static int maxn = (int)(1e6);
尺取法就是左指针和右指针分别从开头开始递增,o(n)复杂度。

猜你喜欢

转载自blog.csdn.net/w1304636468/article/details/88610102