题目
分析
给了一串数,找一个子串使得他们的和大于给定的数S。复杂的方法这里就不多说了,介绍一下尺取法。
基本思想
通过首位缩小区间的长度来求解最小的那个长度具体步骤
给定s, t来表示首尾的一个指针。sum表示当前区间的和,res记录最短的长度。
1.将s=t=sum初始化0
2.只要sum < S,就将t指针向后移,并把S加上后面的一个数。(当sum>S停止)
3.(此时的sum满足条件,但是长度不一定最小)将sum减去最前面的一个数,s向后移动一个。
4.当sum< S时退出循环(本来在操作2的时候应该大于S的,小于S表示从s开始到最后一个数都加上还是不能满足sum大于S,就没有必要继续操作3了)代码
#include <iostream>
using namespace std;
int min(int a, int b)
{
return a < b ? a : b;
}
int main()
{
int test;
cin >> test;
while (test--)
{
int n, s;
cin >> n >> s;
int num[100005] = { 0 };
for (int i = 0; i < n; i++)
cin >> num[i];
long long int res = n + 1, j = 0, i = 0;
long long int sum = 0;
while (1)
{
while (sum < s&&j < n)
sum += num[j++];
if (sum < s) break;
res = min(res, j - i);
sum -= num[i++];
}
if (res>n) cout<<0<<endl;
else cout<<res<<endl;
}
return 0;
}
实际这题也相当于是一种dp,dp[i]表示从i开始向后加和刚好大于S的最小长度,但是当i>某个数的时候即使加到了最后一个数也不一定满足大于S这个条件。因此上面只要在执行了1以后还不能满足就可以退出这个大循环了