蓝桥杯——动态规划

Posted 无乎648

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯——动态规划相关的知识,希望对你有一定的参考价值。

动态规划 导弹拦截

1.动态规划基本概念

1.1动态规划三要素
阶段﹐状态﹐决策。
如果把动态规划的求解过程看成一个工厂的生产线﹐阶段就是生产某个商品的不同的环节,状态就是工件当前的形态﹐决策就是对工件的操作。显然不同阶段是对产品的一个前面各个状态的小结﹐有一个个的小结构成了最终的整个生产线。每个状态间又有关联(下一个状态是由上一个状态做了某个决策后产生的)。
下面举个例子:
要生产一批雪糕﹐在这个过程中要分好多环节∶购买牛奶﹐对牛奶提纯处理﹐放入工厂加工加工后的商品要包装﹐包装后就去销售……,这样每个环节就可以看做是一个阶段﹔产品在不同的时候有不同的状态﹐刚开始时只是白白的牛奶﹐进入生产后做成了各种造型﹐从冷冻库拿出来后就变成雪糕(由液态变成固态=_=l|)。每个形态就是一个状态﹐那从液态变成固态经过了冰冻这一操作﹐这个操作就是一个决策。一个状态经过一个决策变成了另外一个状态,这个过程就是状态转移﹐用来描述状态转移的方程就是状态转移方程。
用图论知识理解动态规划∶把动态规划中的状态抽象成一个点﹐在有直接关联的状态间连一条有向边﹐状态转移的代价就是边上的权。这样就形成了一个有向无环图AOE网。对这个图进行拓扑排序﹐删除一个边后同时出现入度为0的状态在同一阶段。这样对图求最优路径就是动态规划问题的求解。
1.2动态规划的适用范围
动态规划用于解决多阶段决策最优化问题﹐但是不是所有的最优化问题都可以用动态规划解答呢?
一般在题目中出现求最优解的问题就要考虑动态规划了﹐但是否可以用还要满足两个条件:
1.最优子结构(最优化原理)
2.无后效性
最优化原理在下面的最短路径问题中有详细的解答﹔
什么是无后效性呢?
就是说在状态i求解时用到状态j而状态j就解有用到状态k… .状态N。而求状态N时有用到了状态i这样求解状态的过程形成了环就没法用动态规划解答了﹐这也是上面用图论理解动态规划中形成的图无环的原因。也就是说当前状态是前面状态的完美总结﹐现在与过去无关。。。
当然﹐有时换一个划分状态或阶段的方法就满足无后效性了,这样的问题仍然可以用动态规划解。
【问题描述】
某国为了防御敌国的导弹袭击﹐发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度﹐但是以后每一发炮弹都不能高于前一发的高度。某天﹐雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段﹐所以只有一套系统﹐因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)﹐计算这套系
统最多能拦截多少导弹﹐如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
【输入】
单独一行列出导弹依次飞来的高度。
【输出】
两行﹐分别是最多能拦截的导弹数﹐要拦截所有导弹最少要配备的系统数
【输入样例】
389 207155 300 299 170 158 65
【输出样例】
6
2
问题分析:首先,每套拦截系统打出的导弹的高度都不能高于前一发,所以,当我们发现后一发导弹的高度高于前一发时
我们就需要多用一套拦截系统,所以,求需要多少套拦截系统,就是求最长上升子序列,二一套导弹最多能拦截多少枚导弹,也就是找出最长下降子序列,所以,本题就转化成了经典的动态规划了,但是需要注意:本题的时间限制为1.5秒,如果分别求出最长上升子序列再求最长下降子序列时,就会超时,所以我们要把它们压缩到一个循环里面完成,

#include<cstdio>
#include<iostream>
using namespace std;
int v[10005],f[10005],g[10005]=0,1,maxn,minn; 
//maxn表示最长上升子序列长度,minn表示最长下降子序列的长度
int main()

    int n;
    scanf("%d",&n);//输入每枚导弹的高度
    for(int i=1;i<=n;i++)//求最长上升子序列
    
        scanf("%d",&v[i]); 
        f[i]=g[i]=1; 
        for(int j=1;j<i;j++)
        
            if(v[i]<=v[j]) 
            
                f[i]=max(f[i],f[j]+1);
            
            if(v[i]>v[j]) //求最长下降子序列
            
                g[i]=max(g[i],g[j]+1);
            
        
        if(f[i]>maxn) //求出最长上升子序列的长度
        
            maxn=f[i];
        
        if(g[i]>minn) //求出最长下降子序列的长度
        
            minn=g[i];
        
    
    printf("%d %d\\n",maxn,minn); 
    return 0;

以上是关于蓝桥杯——动态规划的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯——动态规划

第十二届蓝桥杯最短路径(动态规划法)

Python | 蓝桥杯进阶第三卷——动态规划

蓝桥杯 ALGO-108最大体积 (动态规划)

蓝桥杯——动态规划专题

蓝桥杯 地宫寻宝 DFS 动态规划