动态规划DP介绍,内含超级玛丽例题

文章介绍了动态规划的基本概念,它用于解决多阶段决策问题,寻找最优决策序列。与分治和贪心算法对比,说明了DP的特点。文章通过超级玛丽跳跃的例子,阐述如何运用动态规划和斐波那契数列计算到达终点的跳跃方案数。
摘要由CSDN通过智能技术生成

定义:

动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果 。

DP与其他算法的区别:

1、dp一般用于解决多阶段决策问题,即每个阶段都要做一个决策,全部的决策是一个决策序列,要你求一个,最好的决策序列使得这个问题有最优解,将待求解的问题分为若干个相互联系的子问题,只在第一次遇到的时候求解,然后将这个子问题的答案保存下来,下次又遇到的时候直接拿过来用即可。

2、dp和分治的不同之处在于分治分解而成的子问题必须没有联系(有联系的话就包含大量重复的子问题,那么这个问题就不适宜分治,虽然分治也能解决,但是时间复杂度太大,不划算),所以用dp的问题和用分治的问题的根本区别在于分解成的子问题之间有没有联系,这些子问题有没有重叠,即有没有重复子问题

3、dp和贪心的不同之处在于每一次的贪心都是做出不可撤回的决策(即每次局部最优),而在dp中还有考察每个最优决策子序列中是否包含最优决策子序列,即是否具有最优子结构性质,贪心中每一步都只顾眼前最优,并且当前的选择是不会依赖以前的选择的,而dp,在选择的时候是从以前求出的若干个与本步骤相关的子问题中选最优的那个,加上这一步的值来构成这一步那个子问题的最优解

例题:

题目:

大家都知道"超级玛丽"是一个很善于跳跃的探险家,他的拿手好戏是跳跃,但它一次只能向前跳一步或两步。有一次,他要经过一条长为n的羊肠小道,小道中有m个陷阱,这些陷阱都位于整数位置,分别是a 1,a 2,....a m,陷入其中则必死无疑。

显然,如果有两个挨着的陷阱,则玛丽是无论如何也跳过不去的。 现在给出小道的长度n,陷阱的个数及位置。

求出玛丽从位置1开始,有多少种跳跃方法能到达胜利的彼岸(到达位置n)。

输入格式 第一行为两个整数n,m 第二行为m个整数,表示陷阱的位置 输出格式 一个整数,表示玛丽跳到n的方案数。

样例输出:

40>=n>=3,m>=1 n>m(陷阱不会在1和n上)

分析:

1、先建一个盛雷的数组,然后根据扫描器的数字(雷的位置),把有雷的位置等于1,

2、然后再建一个数组,该数组专门用斐波那契来求每一项的最优解,如果从第二项开始没有雷,那么该项等于上一项与上上项的和,到最后返回值为第二个数组的最后一项,就是最优解(方案的总数量)

步骤:

package 刷提21;

import java.util.Scanner;

public class 超级玛丽DP {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();// 长度
        int m = sc.nextInt();// 雷的数量
        int leiqu[] = new int[n];// 雷区数组,1代表有雷
        for (int i = 0; i < m; i++) {
            int nextInt = sc.nextInt();
            leiqu[nextInt] = 1;// 把扫描器的值给对应位置上的雷区数组
        }
        sc.close();
        int k = q(n, leiqu); // 求出最多有多少种类跳法
        System.out.println(k);

    }

    // 根据斐波那契来求。
    private static int q(int n, int a[]) {
        int[] dp = new int[n];
        dp[0] = 0;
        dp[1] = 1;
        for (int i = 2; i < n; i++) {
            if (a[i] != 1) {
                dp[i] = dp[i - 1] + dp[i - 2]; // 如果没有雷,则这项等于上一项与上上项的和
            }
        }
        return dp[n - 1];// 返回值为最后一项
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W少年没有乌托邦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值