动态规划算法详解

什么是动态规划算法?

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

基本思想

动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。

动态规划算法介绍

1)动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法

2)动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

3)与分治法不同的是,适合于用动态规划求解的问题,经分解得到的子问题往往不是互相独立的。(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,

进行进一步的求解)

4)动态规划可以通过填表的方式来逐步推进,得到最优解。

下面举个例子:
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。

示例 1:

输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
示例 2:

输入:coins = [2], amount = 3
输出:-1
示例 3:

输入:coins = [1], amount = 0
输出:0

代码示例:

package com.common.utils;

/**
 * @ClassName CoinChange
 * @Description:  动态规划算法,用java解决零钱兑换问题
 * 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
 * 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
 * 你可以认为每种硬币的数量是无限的。
 * @Author: mischen
 * @date: 19:57 2022/12/1
 * @Version 1.0
 */
public class CoinChange {

    public static void main(String[] args) {
        int[] coins = {1,2,5};
        int M = 11;
        int i = coinChage(coins, M);
        System.out.println(i);
        int[] coins1 = {2};
        int t = coinChage(coins1, 3);
        System.out.println(t);
    }
    /**
     *
     * @param coins 代表硬币的种类
     * @param M 代表拼凑的值 11
     * @return
     */
    public static int coinChage(int[] coins, int M) {
        int[] f = new int[M + 1];
        //number of kinds of coins
        int n = coins.length;
        //initialization
        f[0] = 0;
        for (int i = 1; i <= M; i++  ){
            f[i] = Integer.MAX_VALUE;
            //f[X]=min{f[X-2]+1,f[X-5]+1,f[X-7]+1}
            for (int j = 0; j < n; j++) {
                if (i >= coins[j] && f[i-coins[j]] != Integer.MAX_VALUE) {
                    f[i] = Math.min(f[i-coins[j]] + 1, f[i]);
                }
            }
        }

        if (f[M] == Integer.MAX_VALUE) {
            return -1;
        }

        return f[M];

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值