防卫导弹
原题链接
描述
一种新型的防卫导弹可截击多个攻击导弹。它可以向前飞行,也可以用很快的速度向下飞行,可以毫无损伤地截击进攻导弹,但不可以向后或向上飞行。它有一个缺点,尽管它发射时可以达到任意高度,但它只能截击比它上次截击导弹时所处高度低或者高度相同的导弹。现对这种新型防卫导弹进行测试,在每一次测试中,发射一系列的测试导弹(这些导弹发射的间隔时间固定,飞行速度相同),该防卫导弹所能获得的信息包括各进攻导弹的高度,以及它们发射次序。现要求编一程序,求在每次测试中,该防卫导弹最多能截击的进攻导弹数量。
输入
第一行有若干个整数,表示本次测试中进攻导弹的高度,其中导弹数不超过个。
输出
一个整数,表示最多能截击的进攻导弹数。
输入样例 1
36 25 45 17 22 28
输出样例 1
3
来源
聪明的游戏
最长不上升子序列
动态规划版。
假设给了个数,第个数用表示。
假设要选第个,那就要看这个数能不能选,但是要看能不能选,就要知道之前选的最大值是什么,这很明显就产生了后效性。
众所周知,动态规划需要满足一个很关键的条件:无后效性。
无后效性
所谓无后效性原则,指的是这样一种性质:某阶段的状态一旦确定,则此后过程的演变不再受此前各状态及决策的影响。也就是说,“未来与过去无关”,当前的状态是此前历史的一个完整总结,此前的历史只能通过当前的状态去影响过程未来的演变 (资料选自百度百科)。
通俗地来说,动态规划是个小智障。他在进行第i次选择的时候不能考虑,也考虑不到,这个选择是否与第次做出的选择有冲突。
因为动态规划的局限性,聪明的OIers就要给动态规划铺好路,创造出一个无后效性的状态。
再看题目,会发现:只要这个选择本来是对的,选择的最后一个值就是最大值,那么一个新的选择就可以从之前做的所有选择做出最大值。
所以我们就可以得到状态:
- dp[i]: 已a[i]为结尾的前i个最长不上升子序列。
(求最长下降子序列同理)
状态转移方程则为:
dp[i]=max{dp[1~i-1]};
因为默认是先选择自己,所以将dp[0~n]=1。
时间复杂度:。
#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;
}

浙公网安备 33010602011771号