防卫导弹

原题链接

描述

一种新型的防卫导弹可截击多个攻击导弹。它可以向前飞行,也可以用很快的速度向下飞行,可以毫无损伤地截击进攻导弹,但不可以向后或向上飞行。它有一个缺点,尽管它发射时可以达到任意高度,但它只能截击比它上次截击导弹时所处高度低或者高度相同的导弹。现对这种新型防卫导弹进行测试,在每一次测试中,发射一系列的测试导弹(这些导弹发射的间隔时间固定,飞行速度相同),该防卫导弹所能获得的信息包括各进攻导弹的高度,以及它们发射次序。现要求编一程序,求在每次测试中,该防卫导弹最多能截击的进攻导弹数量。

输入

第一行有若干个整数hi(0hi32767)hi(0≤hi≤32767),表示本次测试中进攻导弹的高度,其中导弹数不超过40004000个。

输出

一个整数maxmax,表示最多能截击的进攻导弹数。

输入样例 1

36 25 45 17 22 28

输出样例 1

3

来源

聪明的游戏

最长不上升子序列

动态规划版。


假设给了xx个数,第ii个数用a[i]a[i]表示。

假设要选第ii个,那就要看这个数能不能选,但是要看能不能选,就要知道之前选的最大值是什么,这很明显就产生了后效性

众所周知,动态规划需要满足一个很关键的条件:无后效性

无后效性

所谓无后效性原则,指的是这样一种性质:某阶段的状态一旦确定,则此后过程的演变不再受此前各状态及决策的影响。也就是说,“未来与过去无关”,当前的状态是此前历史的一个完整总结,此前的历史只能通过当前的状态去影响过程未来的演变 (资料选自百度百科)。

通俗地来说,动态规划是个小智障。他在进行第i次选择的时候不能考虑,也考虑不到,这个选择是否与第ix(2x<i)i-x(2≤x<i)次做出的选择有冲突。

因为动态规划的局限性,聪明的OIers就要给动态规划铺好路,创造出一个无后效性的状态。


再看题目,会发现:只要这个选择本来是对的,选择的最后一个值就是最大值,那么一个新的选择就可以从之前做的所有选择做出最大值。

所以我们就可以得到状态

  • dp[i]: 已a[i]为结尾的前i个最长不上升子序列。

(求最长下降子序列同理)

状态转移方程则为:

dp[i]=max{dp[1~i-1]};

因为默认是先选择自己,所以将dp[0~n]=1。

时间复杂度:O(n2)O(n^2)

#include<bits/stdc++.h>
using namespace std;
int a[111111],f[111111],n=1,ans;
int main(){
	cin>>a[n];
	f[1]=1;
	while(getchar()!='\n') {
		cin>>a[++n];
		f[n]=1;
	}
	for(int i=2;i<=n;i++) {
		for(int j=1;j<i;j++)
			if(a[i]<=a[j]) {
				f[i]=max(f[i],f[j]+1);
			}
	}
	for(int i=1;i<=n;i++) ans=max(ans,f[i]);
	cout<<ans;
	return 0;
}
posted @ 2022-04-09 16:10  cjrqwq  阅读(7)  评论(0)    收藏  举报  来源