`
ooaer
  • 浏览: 138851 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

动态规划 入门 二

    博客分类:
  • C++
阅读更多
第二节 动态规划分类讨论

这里用状态维数对动态规划进行了分类:

1.状态是一维的

1.1下降/非降子序列问题:

问题描述:  {挖掘题目的本质,一但抽象成这样的描述就可以用这个方法解}

在一个无序的序列a1,a2,a3,a4…an里,找到一个最长的序列满足:ai<=aj<=ak…<=am,且i<j<k…<m.(最长非降子序列)或ai>aj>ak…>am,且i>j>k…>m.(最长下降子序列)。

问题分析:

如果前i-1个数中用到ak (ak>ai或ak<=ai)构成了一个的最长的序列加上第I个数ai就是前i个数中用到i的最长的序列了。那么求用到ak构成的最长的序列有要求前k-1个数中……

从上面的分析可以看出这样划分问题满足最优子结构,那满足无后效性么?显然对于第i个数时只考虑前i-1个数,显然满足无后效性,可以用动态规划解。

分析到这里动态规划的三要素就不难得出了:如果按照序列编号划分阶段,设计一个状态opt[i] 表示前i个数中用到第i个数所构成的最优解。那么决策就是在前i-1个状态中找到最大的opt[j]使得aj>ai(或aj<=ai),opt[j]+1就是opt[i]的值;用方程表示为:{我习惯了这种写法,但不是状态转移方程的标准写法 }

opt[i]=max(opt[j])+1   (0<=j<i 且aj<=ai)       {最长上升序列}

opt[i]=max(opt[j])+1   (0<=j<i 且aj>ai)        {最长下降序列}

实现求解的部分代码:

      opt[0]:=maxsize;{maxsize 为maxlongint或-maxlongint}

for  i:=1 to n do

for j:=0 to i-1 do

if ( a[j]>a[i]) and (opt[j]+1>opt[i]) then    

  opt[i]:=opt[j]+1;

ans:=-maxlongint;

for i:=1 to n do

if opt[i]>ans then ans:=opt[i];                {ans 为最终解}

复杂度:从上面的实现不难看出时间复杂度为O(N2),空间复杂度O(N);



例题1







拦截导弹

(missile.pas/c/cpp)

来源:NOIP1999(提高组) 第一题

【问题描述】

    某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

   输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

【输入文件】missile.in

  单独一行列出导弹依次飞来的高度。

【输出文件】missile.out

  两行,分别是最多能拦截的导弹数,要拦截所有导弹最少要配备的系统数

【输入样例】

389 207 155 300 299 170 158 65

【输出样例】

6

2

【问题分析】

有经验的选手不难看出这是一个求最长下降序列问题,显然标准算法是动态规划。

以导弹依次飞来的顺序为阶段,设计状态opt[i]表示前i个导弹中拦截了导弹i可以拦截最多能拦截到的导弹的个数。

状态转移方程:

opt[i]=max(opt[j])+1  (h[i]>=h[j],0=<j<i)   {h[i]存,第i个导弹的高度}

最大的opt[i]就是最终的解。

这只解决了第一问,对于第二问最直观的方法就是求完一次opt[i]后把刚才要打的导弹去掉,在求一次opt[i]直到打完所有的导弹,但这样做就错了。

不难举出反例: 6 1 7 3 2     

错解: 6 3 2/1/7   正解:6 1/7 3 2

其实认真分析一下题就回发现:每一个导弹最终的结果都是要被打的,如果它后面有一个比它高的导弹,那打它的这个装置无论如何也不能打那个导弹了,经过这么一分析,这个问题便抽象成在已知序列里找最长上升序列的问题。

求最长上升序列和上面说的求最长非升序列是一样的,这里就不多说了。

复杂度:时间复杂度为O(N2),空间复杂度为O(N)。
 

C++代码
#include<iostream>   
using namespace std;   
int shu[5001];   
int fj[5001];   
int fup[5001];   
int n;   
int main()   
{   
    n=0;   
    int maxa=-564;int maxb=-21321;   
    for(int i=1;i<=5000;i++)   
    {   
            fj[i]=1;   
            fup[i]=1;   
            }   
       
    cin>>n;   
    for(int i=1;i<=n;i++)   
    cin>>shu[i];   
       
      
    for(int i=2;i<=n;i++)   
    {   
       for(int j=i-1;j>=1;j--)   
       {   
        if(shu[i]<=shu[j])   
        {        
         if( fj[i]<fj[j]+1)                                                    
        fj[i]=fj[j]+1;   
        }                                                
               }   
        if(fj[i]>maxa)   
        maxa=fj[i];   
    }   
    for(int i=2;i<=n;i++)   
    {   
       for(int j=i-1;j>=1;j--)   
       {   
        if(shu[i]>=shu[j])   
        {        
         if(fup[i]<fup[j]+1)                                                    
        fup[i]=fup[j]+1;   
        }                                                
               }   
        if(fup[i]>maxb)   
        maxb=fup[i];   
    }   
    cout<<maxa<<" "<<maxb;   
       
       
    return 0;   
    }   
 

转自:http://stumble41.com/article.asp?id=60
分享到:
评论

相关推荐

    ACM动态规划从入门到精通

    而多维动态规划则处理更复杂的数据结构,例如二维甚至更高维度的矩阵,常见于背包问题、图论问题等。 文件"大规模动态过程优化的拟序贯算法研究.nh"可能详细阐述了如何在处理大规模数据时,利用动态规划优化算法的...

    动态规划入门资料,超好

    本资料包是为初学者设计的动态规划入门资源,旨在帮助学习者快速掌握这一核心概念。 动态规划(Dynamic Programming,简称DP)源于1950年代由美国数学家理查德·贝尔曼提出的,其主要思想是将复杂问题分解成子问题...

    动态规划入门练习题

    动态规划入门练习题 标题:动态规划入门练习题 描述:关于动态规划的一些题目,值得一做。 标签:ACM 动态规划 本文档提供了四个动态规划入门练习题,涵盖了石子合并、最小代价子母树、背包问题和商店购物四个方面...

    经典的动态规划入门练习题

    动态规划在这里可以通过创建一个二维数组来表示从起点到各个位置的最低费用,然后根据汽车的油量和加油规则更新这个数组。每到达一个新的加油站,我们会考虑是否在那里加油,并计算两种情况(加油和不加油)下的最低...

    动态规划入门第3课的PPT

    动态规划入门第3课PPT笔记 本笔记涵盖了动态规划的基础知识,并通过实践例题来帮助读者更好地理解动态规划的应用。 动态规划(Dynamic Programming)是一种算法设计方法,通过将复杂的问题拆分成多个小问题,并...

    动态规划_动态规划_

    这个压缩包文件的标题和描述表明,它可能包含了一些基础的动态规划概念和实例,适合初学者入门学习。 动态规划的核心在于将一个复杂的问题分解成多个相互关联的子问题,并通过存储和重用子问题的解来避免重复计算,...

    DP基础 动规 动态规划 基础入门

    动态规划是一种解决问题的有效方法,尤其在计算机科学领域中,它被广泛应用于求解最优化问题。动态规划的核心思想是将复杂的问题分解成一系列更小的子问题,通过存储子问题的解来避免重复计算,从而达到高效求解的...

    动态规划入门详解 很实用

    2. **最优子结构**:许多动态规划问题具有最优子结构,即一个最优解可以通过其子问题的最优解来构造。这是动态规划能够解决问题的基础,因为我们可以从最小的子问题开始,逐步构建整个问题的最优解。 3. **记忆化**...

    动态规划入门

    这个“动态规划入门”资料很可能是为初学者准备的,旨在介绍这一概念并提供实践案例。 动态规划(Dynamic Programming,简称DP)的核心思想是将复杂问题分解为子问题,通过解决这些子问题来构建全局最优解。这种...

    动态规划入门第3课PPTX另一个版本

    在“动态规划入门第3课”的内容中,我们主要探讨了两个经典的问题:背包问题和寻找数列分割使得两堆和的差距最小。 首先,我们来看背包问题。这是一个经典的0-1背包问题,其中涉及到N个物品,每件物品都有自己的...

    动态规划32讲(十分好的资料)

    很好的动态规划的资料。 一共有32讲,并且有动态规划状态转移方程的总结。 第一节 动态规划基本概念 第二节 动态规划分类讨论 动态规划入门3 动态规划入门4 动态规划入门5 动态规划入门6 ...动态规划入门8……

    动态规划-从入门到精通

    在实际应用中,我们通常用一个二维数组(或其他数据结构)来存储这些状态,这个数组称为“动态规划表”。 动态规划可以分为两类:记忆化搜索和自底向上。记忆化搜索是从最简单的子问题开始,逐步解决更复杂的子问题...

    动态规划入门第4、5课

    动态规划是一种解决问题的有效方法,尤其在处理具有重叠子问题和最优子结构的复杂问题时。本篇将深入探讨动态规划的两个实例:求解最长公共子串问题和取数游戏。 首先,我们来看第一个问题——求解两个小写字母组成...

    Minimum Snap轨迹规划详解(1)轨迹规划入门

    轨迹规划详解(1)轨迹规划入门 Minimum Snap轨迹规划是一种常用的轨迹规划方法,主要用于机器人的运动规划。轨迹规划的目的是为了找到一条从起点到终点的平滑曲线,以便控制机器人的运动。 一、轨迹规划是什么?...

    动态规划算法入门指南:从斐波那契数列到爬楼梯问题

    ### 动态规划算法入门指南:从斐波那契数列到爬楼梯问题 #### 一、动态规划算法概述 动态规划(Dynamic Programming,简称DP)是一种强大的算法思想和技术,常用于解决各种优化问题,例如寻找最优解或最大化/最小...

    acm 动态规划 超级经典

    动态规划是一种在计算机科学和数学中广泛使用的算法设计技术,尤其在解决最优化问题时表现突出。它在ACM(国际大学生程序设计竞赛)中是一...通过不断练习和理解,动态规划可以从难以入门的技术转变为解决问题的利器。

Global site tag (gtag.js) - Google Analytics