GDUT_寒假训练题解报告_专题I_A题 个人题解报告【尺取模板题目详解】【poj题目Subsequence】

本文详细解析GDUT寒假训练题Subsequence的尺取算法解题思路,通过实例阐述如何求解序列的连续子序列,使其和大于或等于给定值S,同时分享尺取算法的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GDUT_寒假训练题解报告_专题I_A题 个人题解报告:题目Subsequence

原题链接:http://poj.org/problem?id=3061

A题:尺取(模板题目

给出了一个N长度的正整数序列(10<N<1e5),每个正整数小于或等于10000,以及一个正整数S(S<1e8)。编写一个程序,以求序列的连续元素的子序列的最小长度,其和大于或等于S。
输入
第一行是测试用例的数量。对于每个测试用例,程序必须从第一行读取数字N和S,用间隔分隔。序列的数目在测试用例的第二行中给出,用间隔分隔。输入将以文件的结尾结束。
输出
对于每一种情况,程序必须在输出文件的单独行上打印结果。如果没有答案,则打印0。
样本输入
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
样本输出
2
3

分析:典型的尺取题目,如果暴力做就要设一个起点一个终点走上n(n-1)/2遍,但是用笔一划可以分析出来有些情况完全可以省略,比如序列(l,r),如果满足条件,那么(l,r+1)显然没必要了,因为徒增长度。
那么实际上对于(1,k)这个序列,到底怎么划分呢?

猜想:设原序列里面每个元素分别为(A(0),A(1)…A(n-1))状态f(x),意义为以第x元素结尾的满足条件序列的长度为L,也就是( A(x-L+1)…A(x) )这个序列
状态转移:f(x+1)如果只是尾巴A(x+1)衔上f(x),那么无疑会导致出现分析中的情况,但是因为意义是以x+1结尾的,所以呢,我们从A(x-L+1)开始查看,这个元素可不可以删去?如果可以,那就删去,那我f(x+1)长度就从L+1到了L,循环这个步骤,直到头部不可删去,此时f(x+1)达到了自身意义:以x+1号元素结尾的满足条件的最短序列的长度。

考虑:这个猜想似乎是正确的,每次尾部挪一个位置,然后从头部开始缩,直到缩到不能缩,每次有了一个新的长度,用来更新 int _MIN 的值,就可以了

毛毛虫算法,尺取算法十分有趣,同时加强了我对状态这两个字的理解,

上代码:

using namespace std;
int t,n,s;
int all[100010];
int main()
{
	while ( scanf ( "%d", &t ) != EOF )
	{
		while ( t-- )
		{
			scanf ( "%d %d", &n, &s );
			all[0] = 0;
			for ( int time = 1; time <= n; time++ )
			{
				int num;
				scanf ( "%d", &num );
				all[time] = all[time - 1] + num;
			}
			int _Min = n + 1;
			int left = 0, right = 1;
			if ( all[n] < s )
				printf ( "0\n" );
			else
			{
				while ( right <= n )
				{
					if ( right - left < _Min && all[right] - all[left] >= s )
						_Min = right - left;
					right++;
					while ( all[right] - all[left + 1] >= s )
					{
						left++;
					}
				}
				printf ( "%d\n", _Min );
			}
		}
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值