每天一道动态规划——第一天

news2024/9/17 9:08:23
动态规划一定要去尝试!

题目一:

1)题目描述

一共有N个位置,机器人从当前位置cur走到目标位置aim,有res步可以走,问一共有多少种方法。
题目示例:

1 2 3 4 5 6
N=6|cur=2|aim=3|res=3
结果:1
分析:2-3-4-3

2)代码

public class demo01 {

    public static void main(String[] args) {
        int res = 13;
        int cur = 2;
        int aim = 3;
        int N = 7;

        int result = 0;

        result = process1(cur, aim, res, N);
        System.out.println(result);
        
        int[][] dp = new int[N + 1][res + 1];
        for (int i = 0; i <= N; i++) {
            for (int j = 0; j <= res; j++) {
                dp[i][j] = -1;
            }
        }
        int result2=process2(cur, aim, res, N,dp);
        System.out.println(result2);
    }

    public static int process1(int cur, int aim, int res, int N) {
        /*
        cur:当前位置
        aim:目标位置
        res:剩余步数
        N:共有哪些位置
         */
        if (res == 0) {
            return cur == aim ? 1 : 0;
        }
        if (cur == 1) {
            return process1(2, aim, res - 1, N);
        } else if (cur == N) {
            return process1(N - 1, aim, res - 1, N);
        } else {
            return process1(cur - 1, aim, res - 1, N) + process1(cur + 1, aim, res - 1, N);
        }

    }
    }

3)代码优化

当暴力递归使总是出现重复解,可以通过空间换时间的方法来进行优化。

但当一个暴力递归中不存在重复解,那么它本身就是不可以优化的。

我们总说动态规划的dp表,我觉得最好的理解就是缓存表。

我们可以发现,结果是由cur与res唯一决定的(此时我认为是由状态唯一决定的)。

如果你之前计算过cur还剩res步的时候,此时又要计算,那为什么不用一个二元组把数据记录下来呢?记为dp[cur][res]。

cur的范围为:1~N
res的范围为:0~K
所以对二元状态表进行初始化:
-1为没计算过;
!=-1为计算过;—有缓存先走缓存

优化代码如下:

package com.sq.demo72DynamicPlan;

public class demo01 {
    static int res = 3;
    static int cur = 2;
    static int aim = 3;
    static int N = 7;

    public static void main(String[] args) {

        long start = System.nanoTime();
        int[][] dp = new int[N + 1][res + 1];
        for (int i = 0; i <= N; i++) {
            for (int j = 0; j <= res; j++) {
                dp[i][j] = -1;
            }
        }
        int result2 = process2(cur, aim, res, N, dp);
        long end = System.nanoTime();
        System.out.println(result2);
        System.out.println(end - start);


    }

    public static int process2(int cur, int aim, int res, int N, int[][] dp) {
        /*
        cur:当前位置
        aim:目标位置
        res:剩余步数
        N:共有哪些位置
         */

        if (dp[cur][res] != -1) {
            return dp[cur][res];
        }

        int ans = 0;
        if (res == 0) {
            ans = (cur == aim ? 1 : 0);
        } else if (cur == 1) {
            ans = process2(2, aim, res - 1, N, dp);
        } else if (cur == N) {
            ans = process2(N - 1, aim, res - 1, N, dp);
        } else {
            ans = process2(cur - 1, aim, res - 1, N, dp) + process2(cur + 1, aim, res - 1, N, dp);
        }
        dp[cur][res] = ans;
        return ans;

    }
	}

这种动态规划就是傻缓存,我并不关心你之前的状态,你只要给我当前的状态我就会给你个输出。就像是你只需要输入银行卡号和密码,银行就给你钱,他不关心你跟这个银行卡号和密码的故事。

这种方法的学名叫做:从顶向下的动态规划。 或者缓存法搜索。

4)代码优化2

在这里插入图片描述
上面这张图虽然画的很乱,但是很明了。
根据分析何以知道,如果

	1 2 3 4 5 
	N=5|cur=2|aim=4|res=6

在这种情况下,在res=0,cur=aim=4的时候方法才为1.

所以第4行第0列=1,即dp[4][0]=1;第0列的其余值均为0,即dp[i][0]=0,i≠4。

此处就相当于一个初始条件,也是我们之前学递归时候说的递归结束条件

那我们就不需要递归调用了,只需要根据表格的初始情况以及一些规律,把整张表格填写好了,就可以得出我们想要的结果了。

话不多说,上代码:

public class demo03 {

    static int res = 23;
    static int cur = 2;
    static int aim = 3;
    static int N = 7;

    public static void main(String[] args) {
        ways3(cur, aim, res, N);

    }

    public static void ways3(int cur, int aim, int res, int N) {

        System.out.println("第三种方式");
        long start = System.nanoTime();
        int[][] dp = new int[N + 1][res + 1];

        //第0列是初始条件
        dp[aim][0] = 1;//第0列其余的位置都是0

        for (int i = 1; i <= res; i++) {
            dp[1][i] = dp[2][i - 1];
            for (int j = 2; j < N; j++) {
                dp[j][i] = dp[j - 1][i - 1] + dp[j + 1][i - 1];
            }
            dp[N][i] = dp[N - 1][i - 1];
        }
        long end = System.nanoTime();
        System.out.println("共有方式:"+dp[cur][res]+"种");
        System.out.println("耗时为(ns):"+(end-start));
    }
}

初步入门动态规划就是这些了,我们接下来都要从初始的暴力动态规划,一步步推到这种状态转移过程,加油!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/932787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

suricata初体验+wireshark流量分析

目录 一、suricata介绍 1.下载安装 2.如何使用-攻击模拟 二、wireshark流量分析 1.wireshark过滤器使用 2.wireshark其他使用 一、suricata介绍 1.下载安装 通过官网下载suricata&#xff0c;根据官网步骤进行安装。 官网地址&#xff1a; https://documentation.wazuh.…

Python高光谱遥感数据处理与高光谱遥感机器学习方法应用

本文提供一套基于Python编程工具的高光谱数据处理方法和应用案例。 本文涵盖高光谱遥感的基础、方法和实践。基础篇以学员为中心&#xff0c;用通俗易懂的语言解释高光谱的基本概念和理论&#xff0c;旨在帮助学员深入理解科学原理。方法篇结合Python编程工具&#xff0c;专注…

二叉树的层序遍历及完全二叉树的判断

文章目录 1.二叉树层序遍历 2.完全二叉树的判断 文章内容 1.二叉树层序遍历 二叉树的层序遍历需要一个队列来帮助实现。 我们在队列中存储的是节点的地址&#xff0c;所以我们要对队列结构体的数据域重定义&#xff0c; 以上代码 从逻辑上来讲就是1入队&#xff0c;1出队&am…

【信创】未写完

信创比赛 模块A任务二&#xff1a;docker容器集群管理 模块C子任务一:数据库部署子任务二:数据库参数配置子任务三&#xff1a;数据库管理 模块A 任务二&#xff1a;docker容器集群管理 1.docker run 新建创建容器 2.docker loan 将文件导入镜像库里&#xff08;将该文件变成镜…

DDR PHY

1.ddr phy架构 1.pub&#xff08;phy unility block&#xff09; 支持特性&#xff1a; &#xff08;1&#xff09;不支持SDRAM的DLL off mode &#xff08;2&#xff09;数据位宽是以8bit逐渐递增的&#xff08;这样做的目的是因为可能支持16/32/64bit的总线位宽&#xff…

STM32F103 4G Cat.1模块EC200S使用

一、简介 EC200S-CN 是移远通信最近推出的 LTE Cat 1 无线通信模块&#xff0c;支持最大下行速率 10Mbps 和最大上行速率 5Mbps&#xff0c;具有超高的性价比&#xff1b;同时在封装上兼容移远通信多网络制式 LTE Standard EC2x&#xff08;EC25、EC21、EC20 R2.0、EC20 R2.1&a…

QtCreator指定Windows Kits版本

先说下事件起因&#xff1a;之前一直在用Qt5.12.6&#xff0b;vs2017在写程序&#xff0c;后面调研了一个开源库Qaterial&#xff0c;但是翻来覆去的编译都有问题&#xff0c;后面升级到了Qt5.15.2&#xff0b;vs2019来进行cmake的编译&#xff0c;搞定了Qaterial&#xff0c;但…

家长如何将ChatGPT成为家庭日常活动的得力助手

人工智能已经在许多领域发挥作用&#xff0c;如播放音乐、关闭灯光和帮助我们更安全地驾驶。那么&#xff0c;在养育孩子方面呢&#xff1f; 使用像ChatGPT这样的应用&#xff0c;家长们可以更好地完成任务&#xff0c;但同时也要了解其中存在的风险。 许多家长表示&#xff…

KVM创建虚拟机可访问外网+可使用Xshell等工具连接

创建虚拟机时使用桥接网络模块即可&#xff0c;如下&#xff1a; 1、创建一个存储卷(虚拟机的磁盘) 2、创建虚拟机时选择网络 3、系统安装完成后配置固定IP地址 vi /etc/sysconfig/network-scripts/ifcfg-eth0ONBOOTyes BOOTPROTOstatic IPADDR16.32.15.60 GATEWAY16.32.15.2…

【JasperReport笔记05】JasperReport指定自定义字体文件,解决中文不显示问题

这篇文章&#xff0c;主要介绍JasperReport指定自定义字体文件&#xff0c;解决中文不显示问题。 目录 一、自定义字体文件 1.1、创建字体配置文件 1.2、创建fonts.xml字体文件 1.3、在Jasper Studio中添加字体 1.4、指定模板文件 1.5、案例代码 1.6、运行测试 1.7、服…

Base64与cv2读取的图片,格式互转

Base64编码 Base64编码是一种将二进制数据转换为可打印字符的方式&#xff0c;以便在文本格式中传输或存储。它通常用于将二进制数据编码为ASCII字符串&#xff0c;以便在电子邮件、网页或XML文件中传输。 Base64编码的原理是将3个8位字节的数据&#xff08;即24位二进制数据…

最近在干什么

不知不觉这个月要过去一大半了&#xff0c;说好的一个月更新一两篇博客又要食言了。就来随便聊聊最近在干的事吧。 以图说话&#xff0c;作为程序员还有什么比 Git 提交记录更好说明你最近工作状态的呢。 当然这里所有的提交记录仅仅来自一个 Repository (库) &#xff0c;就是…

【Acwing338】计数问题题解

题目描述 举个栗子分类讨论 求a~b中x的个数&#xff0c;可以转换为1~b中x的个数减去1~a-1中x的个数 所以核心是求1~n中x的个数&#xff0c;可以转换为求x在1~n中每一个数的每一位上出现的次数的和 假设要求1~abcdefg&#xff08;这是一个七位数&#xff09;中x1的个数&#…

Shell基础_Shell概述及脚本执行方式

文章目录 1. Shell概述1.1 Shell是什么1.2 Shell的分类1.3 Linux支持的Shell1.4 总结 2. Shell脚本的执行方式2.1 echo输出命令2.2 第一个脚本2.3 脚本执行 1. Shell概述 1.1 Shell是什么 Shell是一个命令行解释器&#xff0c;它为用户提供了一个向Linux内核发送请求以便运行…

深度学习8:详解生成对抗网络原理

目录 大纲 生成随机变量 可以伪随机生成均匀随机变量 随机变量表示为操作或过程的结果 逆变换方法 生成模型 我们试图生成非常复杂的随机变量…… …所以让我们使用神经网络的变换方法作为函数&#xff01; 生成匹配网络 培养生成模型 比较基于样本的两个概率分布 …

结合源码拆解Handler机制

作者&#xff1a;Pingred 前言 当初在讲App启动流程的时候&#xff0c;它的整个流程涉及到的类可以汇总成下面这张图&#xff1a; 那时着重讲了AMS、PMS、Binder这些知识点&#xff0c;有一个是没有对它进行详细讲解的&#xff0c;那就是常见的Handler&#xff0c;它不仅在这个…

一篇掌握BFD技术(一):静态路由与BFD联动配置

1. 实验目的 熟悉静态路由与BFD联动的应用场景掌握静态路由与BFD联动的配置 2. 实验拓扑 想要华为数通配套实验拓扑和配置笔记的朋友们点赞关注&#xff0c;评论区留下邮箱发给你 3. 实验步骤 1&#xff09;配置IP地址 AR1的配置 <Huawei>system-view Enter system…

Linux——socket网络通信

一、什么是socket Socket套接字 由远景研究规划局&#xff08;Advanced Research Projects Agency, ARPA&#xff09;资助加里福尼亚大学伯克利分校的一个研究组研发。其目的是将 TCP/IP 协议相关软件移植到UNIX类系统中。设计者开发了一个接口&#xff0c;以便应用程序能简单地…

继续深挖,Jetpack Compose的State快照系统

Jetpack Compose 有一种特殊的方式来表示状态和传播状态变化&#xff0c;从而驱动最终的响应式体验&#xff1a;状态快照系统&#xff08;State snapshot system&#xff09;。这种响应式模型使我们的代码更加强大和简洁&#xff0c;因为它允许组件根据它们的输入自动重组&…

Docker安装及Docker构建简易版Hadoop生态

一、首先在VM创建一个新的虚拟机将Docker安装好 更新系统&#xff1a;首先打开终端&#xff0c;更新系统包列表。 sudo apt-get update sudo apt-get upgrade下图是更新系统包截图 安装Docker&#xff1a;使用以下命令在Linux上安装Docker。 sudo apt-get install -y docker.i…