首页 > 编程语言 >算法 - 动态规划

算法 - 动态规划

时间:2022-10-02 21:26:15浏览次数:55  
标签:int OptionalInt 算法 ans var new 动态 规划

动态规划技术的核心是“子问题划分”和“记忆化”。比如,leetcode#70. 爬楼梯与leetcode#120. 三角形最小路径和。#70的子问题划分是这样的 ---- 由于每次只能向上爬一个或两个台阶,所以,爬到最高层的楼梯的路径数 \(f(n)\) 一定是爬到最高层往下一层的路径数 \(f(n-1)\) 与往下两层的路径数 \(f(n-2)\) (如果存在的话)之和。而#70的记忆化是这样的 ---- 如果按照从目标到起点的子问题划分方式来计算的话,那就是将递归思想实现为递归算法。但是,递归算法存在重复计算的情况,比如计算 \(f(n-1)\) 的时候也会计算一次 \(f(n-2)\)。记忆化就是一种用空间换取时间的算法,毕竟,如果问题规模即楼梯数有限的话,将中间数据全部列出来所消耗的内存一般情况也是可以接受的。而且,大多数情况又是可以用“滚动数组”的思想,将内存消耗压缩到\(O(1)\)。斐波那契数列问题的求解也是如此。对于#120来说,子问题的划分是这样的 ---- 假设到最高层以下所有节点的路径花费都已经计算出来了,那么从跟节点到叶子节点的最佳路径就是从所有第二层节点中选择一个最小的。于是,算法就是从最底层一直往上求解。只是这里的记忆化是无法用滚动数组来压缩内存消耗的。
另外,再来看leetcode#322例子中的一个细节点,即,某些子孙问题可能是不存在结果的,这种不存在在个别情况下是无需考虑的,比如#70中所有的子问题都是有解且每个子问题对最终解都是有用的。这里可以统一为记忆化数组填充一个最值,或者像Java的Optional类型那样单独用一个字段或是否为空来表示存在与否,示例代码如下。

// leetcode#322
import java.util.Arrays;
import java.util.OptionalInt;

class Solution {
    public static void main(String[] args) {
        var s = new Solution();
        var coins = new int[][]{{1, 2, 5}, {2}, {1}};
        var amount = new int[]{11, 3, 0}; // 5+5+1,
        var ans = new int[]{3, -1, 0};
        for (int i = 0; i < ans.length; ++i) {
            System.out.println(ans[i] == s.coinChange(coins[i], amount[i]));
        }
    }

    public int coinChange(int[] coins, int amount) {
        OptionalInt[] ans = new OptionalInt[amount + 1];
        Arrays.fill(ans, OptionalInt.empty());
        ans[0] = OptionalInt.of(0);
        for (int i = 1; i <= amount; ++i) {
            for (var c : coins) {
                int iMinusCoin = i - c;
                if (iMinusCoin < 0 || ans[iMinusCoin].isEmpty()) { // breakdown
                    continue;
                }
                if (ans[i].isPresent()) {
                    ans[i] = OptionalInt.of(Math.min(ans[iMinusCoin].getAsInt() + 1, ans[i].getAsInt()));
                } else {
                    ans[i] = OptionalInt.of(ans[iMinusCoin].getAsInt() + 1);
                }
            }
        }
        return ans[amount].orElse(-1);
    }
}

标签:int,OptionalInt,算法,ans,var,new,动态,规划
From: https://www.cnblogs.com/qqiwei/p/16749480.html

相关文章

  • 数据结构与算法【Java】09---多路查找树
    目录前言1、二叉树与B树1.1、二叉树的问题分析1.2、多叉树1.3、B树的基本介绍2、2-3树2.1、2-3树简介2.2、2-3树应用案例2.3、补充3、B树、B+树和B*树3.1、B树的简......
  • 最短路径算法
    研究生考试中图论中求解最短路径的算法主要有两种,Dijkstra算法及Floyd算法,其中Dijkstra算法用于求解单源最短路径问题,而Floyd算法则用于解决多源最短路径问题。本文对这两......
  • 最小生成树算法
    最小生成树是指在一个图中,由连接所有顶点的边构成的权值之和最小的树,求最小生成树的算法主要有Prim算法及Kruskal算法,此处介绍Prim算法的基本原理。Prim算法是一种贪心算......
  • Spring AOP基础之代理模式.静态代理和动态代理
    代理模式一、代理模式介绍代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展......
  • 爬山算法&&模拟退火
    constdoubledown=0.996;//降温系数constdoubleeps=1e-15;//终止温度doubleansx,ansy,answ,T;structpoint{intx,y,w;}a[Z];inlinedoubledis(doub......
  • AES加密算法原理及python实现
    AES对称加密算法  AES加密算法即密码学中的高级加密标准(AdvancedEncryptionStandard,AES),又称Rijndael加密法(2000年10月2日,比利时密码专家JoanDaemen和VincentRijmen提......
  • 在强化学习算法性能测试时使用训练好的模型运行游戏,此时如何控制实时游戏画面的帧数
    问题:在强化学习算法性能测试时使用训练好的模型运行游戏,此时如何控制实时游戏画面的帧数?  ========================================  看到很多训练好的模型与游戏交......
  • 强化学习的REIINFORCE算法和交叉熵RL算法
    注意:本文并不讲REINFORCE算法,而是讲强化学习的交叉熵算法,关于REINFORCE算法可以参看:   ==========================================   强化学习有多种分类方法,其中一......
  • BF(暴力求解算法)
    BF(暴力求解算法)即是暴力(BruteForce)算法,是普通的模式匹配算法,BF算法的思想就是将目标串T的第一个字符和主串的S的第一个字符进行匹配,若相等,则则继续匹配T串和S串的第二......
  • C++实现双向RRT算法
    C++实现双向RRT算法背景介绍RRT(Rapidly-exploringRandomTrees)是StevenM.LaValle和JamesJ.KuffnerJr.提出的一种通过所及构建空间搜索树实现对非凸高维空间快速搜......