尺取法-- POJ3061

简单的尺取法的题:

【试题描述】

给定长度为n的正整数数列A(A1, A2, ... , An)以及正整数S,求出总和不小于S的连续子序列的长度的最小值。如果解不存在,则输出0。

 【输入】

第一行两个整数N和S,第二行包括n个正整数表示数列A,两两之间用空格分隔。

【输出】

一个符合题目要求的整数。

【输入示例】

5 11
1 2 3 4 5

【输出示例】
3

【其他说明】

数据范围:10 < N < 10^5,0 < Ai < 10^4+1,S < 10^8.

思路:

            

                     定义一个sum用来记录和是否大于S;

         定义一个cut和cutt,用cutt储存最小的长度,则cut记录一般的值

         程序要分情况讨论:

         1、sum<S

         2、sum≥S

下面是代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 int a[100000];
 5 int main()
 6 {
 7     int n,s,sum=0,cnt=0,cntt=INT_MAX;//cntt先为最大值 
 8     int i,j;
 9     cin>>n>>s;//输入 
10     for(i=0;i<n;i++)//输入 
11     cin>>a[i];
12     i=0;j=0;//先清零 
13     sum=a[0];//为后面的j++少加的数,先加上 
14     cnt=1;//至少为一 
15     while(i<=j&&j<n)//尺取法的边界条件 
16     {
17         if(sum<s)//第一种情况 
18         {
19             j++;//先j++就可以避免最后cnt多加 
20             sum+=a[j];//累计连续数串的和 
21             cnt++;//统计个数 
22         }
23         else//第二种情况 
24         {
25             cntt=min(cnt,cntt);//判断大小 
26             sum-=a[i];//扔掉前一个数 
27             cnt--;//因为扔掉了前一个数,所以个数-1 
28             i++;//前面删去的数的位置 
29         }
30     }
31     if(cntt==INT_MAX) cout<<0;//如果cntt没变,输出0
32     else cout<<cntt;//否则,输出cntt 
33     return 0;
34 }

总的来说:小了就往后加一个同时记录数据,如果大或等于了就减去开头的数同时记录数据;

                    

                        

猜你喜欢

转载自www.cnblogs.com/zqm20041024/p/9371434.html