LA 2678 - Subsequence

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=679

  输入一个N,和一个S,第二行输入N的整数,要求的是由这N个数组成的数列中,一个连续的子数列的和大于或等于S时,这个子数列的长度最小是多少?

解题报告:算法竞赛入门经典上的题,一开始用自己的思路去做,按照我的思路时间更短,但一直WA,不知道为什么,我的思路就是设置两个指针,一个指向子数列的开头的前一个,另一个指向子数列的最后一个,然后在循环条件j <= N的条件下,另外设一个sum 保存当前的子数列的和,然后判断如果当前子数列的和比S小,则将尾指针向后移动一位并将sum的值相应的增加,如果判断出来当前子数列的和比S大,则判断当前子数列的长度并且比较是否是最短的,然后将子数列的前指针向后移动一位,同时将sum的值减去相应的值,这样最后得出的长度最小的子数列的长度便是我们要的答案。但是不知道是有漏洞还是算法本来就不可行,交上去一直WA,麻烦如果知道的童鞋告诉我一下。然后看了大白书之后,有一种新的算法,我觉得没我的快,但结果是对的,没办法。他的做法是先预处理,求出从第一个数到第 i 个数的和并保存起来,然后只要枚举尾节点,然后内层再嵌套一个循环判断满足

到这个尾节点的和大于等于S的前头节点最大的也就是长度最小的子数列。

下面是我的错误代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 
 6 const int maxn = 100000;
 7 int A[maxn+5];
 8 
 9 int main()
10 {
11     int N,S;
12     while(scanf("%d%d",&N,&S)!=EOF)
13     {
14         A[0] = 0;
15         for(int i = 1;i <= N;++i)
16         scanf("%d",&A[i]);
17         int i = 0,j = 0,ans = 0x7ffffff,sum = 0;
18         while(j <= N)
19         {
20             if(sum < S)
21             sum += A[++j];   //当前子数列的和小于S时,尾节点向后移动,并加上后一个节点的值 
22             else
23             {
24                 ans = min(ans,j - i); //当前子数列的和大于等于S时,先判断是不是长度最小的,然后再把前指针往后移动 
25                 i++;
26                 sum -= A[i];
27             }
28         }
29         printf(ans>100000? "0":"%d\n",ans);
30     }
31     return 0;
32 }
33                 
View Code

下面是AC的代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 
 6 const int maxn = 100000;
 7 int A[maxn+5];
 8 
 9 int main()
10 {
11     int N,S;
12     while(scanf("%d%d",&N,&S)!=EOF)
13     {
14         A[0] = 0; 
15         for(int i = 1;i <= N;++i)
16         {
17             scanf("%d",&A[i]);
18             A[i] = A[i-1] + A[i];
19         }
20         int ans = 0x7ffffff,j = 0,flag = 0;
21         for(int i = 1;i <= N;++i)
22         if(A[i] - A[j] >= S)
23         {
24             while(A[i] - A[j+1] >= S) j++;
25             if(i - j < ans)
26             {
27                 flag = 1;
28                 ans = i - j;
29             }
30         }
31         printf(flag? "%d\n":"0\n",ans);
32     }
33     return 0;
34 }
35             
View Code

 

posted @ 2013-09-28 20:37  xiaxiaosheng  阅读(850)  评论(0编辑  收藏  举报