GDUT_寒假訓練題解報告_專題I_A題 個人題解報告【尺取模板題目詳解】【poj題目Subsequence】

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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章