经典DP。
最多一次可以拦截的导弹数,就是在数列中找到一个最长不上升子序列,需要多少防卫导弹就是求一个最长上升子序列。
up[i]表示以第i个为结尾的子序列中最长的不上升子序列的长度。up[i]=max{up[j] + 1}(h[j]>=h[i])。
down[i]表示以第i个为结尾的子序列中最长的上升子序列的长度。down[i]=max{down[j] + 1}(h[j]<h[i])。
一开始没有看出来需要多少防卫导弹就是求一个最长上升子序列,纠结了半天,看了别人的题解才明白的。有点水了,好歹以前还做过这题的,都忘了。。。
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int n,h[1100];
int up[1100],down[1100];
int main()
{
while (scanf("%d",&n) != EOF)
{
up[0] = -1;
down[0] = -1;
for (int i = 1 ; i <= n ; i ++)
{
scanf("%d",&h[i]);
up[i] = 1;
down[i] = 1;
}
for (int i = 1 ; i <= n ; i ++)
{
for (int j = 1 ; j < i ; j ++)
{
if (h[j] >= h[i]) up[i] = up[i]>up[j]+1 ? up[i] : up[j]+1;
if (h[j] < h[i]) down[i] = down[i]>down[j]+1 ? down[i] : down[j]+1;
}
up[0] = up[0]>up[i] ? up[0] : up[i];
down[0] = down[0]>down[i] ? down[0] : down[i];
}
printf("%d %d\n",up[0],down[0]);
}
}