百练 / 2017计算机学科夏令营上机考试: E(最长有序子列)

题目来源:http://noi.openjudge.cn/ch0206/4977/

4977:怪盗基德的滑翔翼

总时间限制: 1000ms  内存限制: 65536kB

描述

怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯。而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼。

有一天,怪盗基德像往常一样偷走了一颗珍贵的钻石,不料却被柯南小朋友识破了伪装,而他的滑翔翼的动力装置也被柯南踢出的足球破坏了。不得已,怪盗基德只能操作受损的滑翔翼逃脱。

假设城市中一共有N幢建筑排成一条线,每幢建筑的高度各不相同。初始时,怪盗基德可以在任何一幢建筑的顶端。他可以选择一个方向逃跑,但是不能中途改变方向(因为中森警部会在后面追击)。因为滑翔翼动力装置受损,他只能往下滑行(即:只能从较高的建筑滑翔到较低的建筑)。他希望尽可能多地经过不同建筑的顶部,这样可以减缓下降时的冲击力,减少受伤的可能性。请问,他最多可以经过多少幢不同建筑的顶部(包含初始时的建筑)?

 

输入

输入数据第一行是一个整数KK < 100),代表有K组测试数据。
每组测试数据包含两行:第一行是一个整数N(N < 100),代表有N幢建筑。第二行包含N个不同的整数,每一个对应一幢建筑的高度h0 < h < 10000),按照建筑的排列顺序给出。

输出

对于每一组测试数据,输出一行,包含一个整数,代表怪盗基德最多可以经过的建筑数量。

样例输入

3

8

300 207 155 299 298 170 158 65

8

65 158 170 298 299 155 207 300

10

2 1 3 4 5 6 7 8 9 10

样例输出

6

6

9

-----------------------------------------------------

解题思路

最长有序子列问题

动态规划

从第0个元素开始,依次计算以第i个元素为末尾的最长有序子列,计算出n个最长有序子列(分别以a[0]~a[n-1]结尾)后,取最长者即计算结果

注意有2个逃跑方向:从左向右/从右向左,故要计算2遍动态规划

-----------------------------------------------------

代码

// 最长有序子列问题
// 注意正序和反序都可以,所以要做2遍

#include
#include
#include
#include
using namespace std;

int main()
{
#ifndef ONLINE_JUDGE
	int n, i, k, j, jj, tmp, ans1, ans2;
	vector buil;
	ifstream fin("xly2017E.txt");
	fin >> n;
	for (i=0; i> k;
		buil.clear();
		for (j=0; j> tmp;
			buil.push_back(tmp);
		}
		if (k==1)
		{
			cout << 1 << endl;
			continue;
		}
		int *substr = new int[k];
		substr[0] = 1;
		// 最大升序子列长度
		for (j=1; j= 0; jj--)
			{
				if (buil.at(jj) < buil.at(j) && substr[jj] > tmp)
				{
					tmp = substr[jj];
				}
			}
			substr[j] = tmp+1;
		}
		tmp = 0;
		for (j=0; j tmp)
			{
				tmp = substr[j];
			}
		}
		ans1 = tmp;
		// 最大降序子列长度
		for (j=1; j= 0; jj--)
			{
				if (buil.at(jj) > buil.at(j) && substr[jj] > tmp)
				{
					tmp = substr[jj];
				}
			}
			substr[j] = tmp+1;
		}
		tmp = 0;
		for (j=0; j tmp)
			{
				tmp = substr[j];
			}
		}
		ans2 = tmp;
		cout << ((ans1>ans2)?ans1:ans2) << endl;
		delete[] substr;
	}
	fin.close();
	return 0;
#endif
#ifdef ONLINE_JUDGE
	int n, i, k, j, jj, tmp, ans1, ans2;
	vector buil;
	cin >> n;
	for (i=0; i> k;
		buil.clear();
		for (j=0; j> tmp;
			buil.push_back(tmp);
		}
		if (k==1)
		{
			cout << 1 << endl;
			continue;
		}
		int *substr = new int[k];
		substr[0] = 1;
		// 最大升序子列长度
		for (j=1; j= 0; jj--)
			{
				if (buil.at(jj) < buil.at(j) && substr[jj] > tmp)
				{
					tmp = substr[jj];
				}
			}
			substr[j] = tmp+1;
		}
		tmp = 0;
		for (j=0; j tmp)
			{
				tmp = substr[j];
			}
		}
		ans1 = tmp;
		// 最大降序子列长度
		for (j=1; j= 0; jj--)
			{
				if (buil.at(jj) > buil.at(j) && substr[jj] > tmp)
				{
					tmp = substr[jj];
				}
			}
			substr[j] = tmp+1;
		}
		tmp = 0;
		for (j=0; j tmp)
			{
				tmp = substr[j];
			}
		}
		ans2 = tmp;
		cout << ((ans1>ans2)?ans1:ans2) << endl;
		delete[] substr;
	}
	return 0;
#endif
}


你可能感兴趣的:(百练OJ/poj,基础算法)