I - 最少拦截系统

I - 最少拦截系统

题目入口:I - 最少拦截系统

解题思路

第一遍遍历前推WA了(很多人想知道为什么会错)
找到题目里的坑就豁然开朗了
虽然是导弹依次飞来
但是后面发射的导弹可以选择前面已用过的拦截系统进行拦截
这里给一个拆分例子理解一下
示例:

8 389 207 155 300 299 170 158 65
389 207 155 65
300 299 170 158

这个样例显然不明显
我们再来一组样例

6 300 288 290 289 187 266
300 290 289 187
288 266

所以答案是2
按照遍历前推则是3
是不是显然了
我们说正确的思路
有这么三个导弹 288 266 299
这种情况下我们肯定需要两个拦截系统来搞它们
第一个解决288 第二个解决299
因此可以想象
所有导弹打出来有几个不连续递增的导弹
就用多少个拦截系统搞掉它们
所以最终问题化为求最大不连续递增子列长度
好了 到了这里dp就可以出来了

使用模版

【模版】数组最大不连续递增子序列

AC代码

#include 
#include 
#include 
#define MaxSize 30010  //注意依题更改数组大小
using namespace std;
int dp[MaxSize];    //存放当前最大不连续递增子列长度
int MCAO(int a[], int n){    //MaxChildArrayOrder
    for (int i = 0; i < n; i++) dp[i] = 1;  //初始化子列长度都为1
    for (int i = 1; i < n; i++)
        for (int j = 0; j < i ; j++)
            if (a[i] > a[j] && dp[j]+1 > dp[i])
                //如果a[i]比它前面的数大且子列长度小于前面小数维护的子列长度+1
                //则更新当前子列长度 (dp核心思想)
                dp[i] = dp[j] + 1;
    int Max = dp[0];
    for (int i = 1; i < n; i++) Max = max(Max, dp[i]);  //取出最大不连续递增子列长度
    return Max;
}
int main() {
    int n;
    while (~scanf("%d", &n)){    //元素个数
        int a[MaxSize];     //存放原始数据
        for (int i = 0; i < n; i++) scanf("%d", &a[i]); //获取元素
        printf("%d\n", MCAO(a, n));  //求最大不连续递增子列长度
    }
    return 0;
}

你可能感兴趣的:(动态规划)