【16】暴力递归改dp(上)

news2024/9/23 19:20:28

目录

一.机器人问题

二.最少硬币问题


一.机器人问题

题目:N表示位置1-N,S表示机器人开始位置,e表示结尾位置,k表示机器人必须走k步,问一共有多少种方法?

情况:

  • 如果第1个位置,下次只能向第2个位置走
  • 如果第N个位置,下次只能向N-1个位置走
  • 若一般位置cur,下次可以向cur-1和cur+1位置走

暴力递归版本: 

	public static int ways1(int N, int M, int K, int P) {
		// 参数无效直接返回0
		if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {
			return 0;
		}
		// 总共N个位置,从M点出发,还剩K步,返回最终能达到P的方法数
		return walk(N, M, K, P);
	}

	// N : 位置为1 ~ N,固定参数
	// cur : 当前在cur位置,可变参数
	// rest : 还剩res步没有走,可变参数
	// P : 最终目标位置是P,固定参数
	// 该函数的含义:只能在1~N这些位置上移动,当前在cur位置,走完rest步之后,停在P位置的方法数作为返回值返回
	public static int walk(int N, int cur, int rest, int P) {
		// 如果没有剩余步数了,当前的cur位置就是最后的位置
		// 如果最后的位置停在P上,那么之前做的移动是有效的
		// 如果最后的位置没在P上,那么之前做的移动是无效的
		if (rest == 0) {
			return cur == P ? 1 : 0;
		}
		// 如果还有rest步要走,而当前的cur位置在1位置上,那么当前这步只能从1走向2
		// 后续的过程就是,来到2位置上,还剩rest-1步要走
		if (cur == 1) {
			return walk(N, 2, rest - 1, P);
		}
		// 如果还有rest步要走,而当前的cur位置在N位置上,那么当前这步只能从N走向N-1
		// 后续的过程就是,来到N-1位置上,还剩rest-1步要走
		if (cur == N) {
			return walk(N, N - 1, rest - 1, P);
		}
		// 如果还有rest步要走,而当前的cur位置在中间位置上,那么当前这步可以走向左,也可以走向右
		// 走向左之后,后续的过程就是,来到cur-1位置上,还剩rest-1步要走
		// 走向右之后,后续的过程就是,来到cur+1位置上,还剩rest-1步要走
		// 走向左、走向右是截然不同的方法,所以总方法数要都算上
		return walk(N, cur + 1, rest - 1, P) + walk(N, cur - 1, rest - 1, P);
	}

暴力递归不好:f(2, 2)展开算过一次,下一次f(2,2)还是展开计算,所以存在很多重复解。 

记忆化版本:

public static int ways1(int N, int M, int K, int P) {
		// 参数无效直接返回0
		if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {
			return 0;
		}
		int[][] dp=new int[K+1][N+1];
		for(int i=0;i<=K;i++) {
			for(int j=0;j<=N;j++) {
				dp[i][j]=-1;
			}
		}
		// 总共N个位置,从M点出发,还剩K步,返回最终能达到P的方法数
		return walk(N, M, K, P, dp);
	}

	public static int walk(int N, int cur, int rest, int P, int[][] dp) {
		
		if(dp[rest][cur]!=-1) {
			return dp[rest][cur];
		}
		if (rest == 0) {
			dp[rest][cur]=cur == P ? 1 : 0;
		}
		else if (cur == 1) {
			dp[rest][cur]=walk(N, 2, rest - 1, P, dp);
		}
		else if (cur == N) {
			dp[rest][cur]=walk(N, N - 1, rest - 1, P, dp);
		}
		else {
			dp[rest][cur]=walk(N, cur + 1, rest - 1, P, dp) + walk(N, cur - 1, rest - 1, P, dp);
		}
		return dp[rest][cur];
	}

动态规划版本:

边界条件 <=>  初始化条件

递归改动态规划 <=> 翻译出依赖关系

	public static int ways2(int N, int M, int K, int P) {
		// 参数无效直接返回0
		if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {
			return 0;
		}
		int[][] dp = new int[K + 1][N + 1];
		dp[0][P] = 1;
		for (int i = 1; i <= K; i++) {
			for (int j = 1; j <= N; j++) {
				if (j == 1) {
					dp[i][j] = dp[i - 1][2];
				} else if (j == N) {
					dp[i][j] = dp[i - 1][N - 1];
				} else {
					dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j + 1];
				}
			}
		}
		return dp[K][M];
	}

二.最少硬币问题

题目:给出N枚硬币,可以能存在重复面值硬币,每枚硬币只能使用一次,求组合出aim数值的所需的最少硬币数。

从左到右逐个硬币考虑,当发现方法一定不可行,直接返回-1

暴力递归版本:

	public static int minConins1(int[] arr, int aim) {
		return process(arr, 0, aim);
	}
	
	public static int process(int[] arr, int index, int rest) {
		if(rest<0) {
			return -1;
		}
		if(rest==0) {
			return 0;
		}
		// rest > 0
		if(index==arr.length) {
			return -1;
		}
		// rest > 0 并且还有硬币
		int p1 = process(arr, index+1, rest);
		int p2Next = process(arr, index+1, rest-arr[index]);
		if(p1==-1&&p2Next==-1) {
			return -1;
		}
		else {
			if(p1==-1) {
				return p2Next+1;
			}
			else if(p2Next==-1) {
				return p1;
			}
			else return Math.min(p1, p2Next+1);
		}
	}

 记忆化版本:

	public static int minConins2(int[] arr, int aim) {
		int[][] dp=new int[arr.length+1][aim+1];
		for(int i=0;i<=arr.length;i++) {
			for(int j=0;j<=aim;j++) {
				dp[i][j]=-2;
			}
		}
		return process(arr, 0, aim, dp);
	}
	
	public static int process(int[] arr, int index, int rest, int[][] dp) {
		if(rest<0) {
			return -1;
		}
		if(dp[index][rest] != -2) {
			return dp[index][rest];
		}
		if(rest==0) {
			dp[index][rest] = 0;
		}
		else if(index==arr.length) {
			dp[index][rest] = -1;
		}
		else {
			// rest > 0 并且还有硬币
			int p1 = process(arr, index+1, rest, dp);
			int p2Next = process(arr, index+1, rest-arr[index], dp);
			if(p1==-1&&p2Next==-1) {
				dp[index][rest] = -1;
			}
			else {
				if(p1==-1) {
					dp[index][rest] = p2Next+1;
				}
				else if(p2Next==-1) {
					dp[index][rest] = p1;
				}
				else dp[index][rest] = Math.min(p1, p2Next+1);
			}
		}
		return dp[index][rest];
	}
	

动态规划版本:

	public static int minCoins3(int[] arr, int aim) {
		int[][] dp=new int[arr.length+1][aim+1];
		
		for(int i=0;i<=arr.length;i++) {
			dp[i][0]=0;
		}
		
		for(int i=0;i<=aim;i++) {
			dp[arr.length][rest] = -1;
		}
		
		for(int index = N-1;index >= 0 ;index--) {
			for(int rest=1;rest<=aim;rest++) {
				
				int p1=dp[index+1][rest];
				int p2Next=-1;
				if(rest-arr[index] >= 0) {
					p2Next = dp[index+1][rest-arr[index]];
				}
				if(p1==-1&&p2Next==-1) {
					dp[index][rest]=-1;
				}
				else {
					if(p1==-1) {
						dp[index][rest] = p1;
					}
					else if(p2Next==-1) {
						dp[index][rest] = p2Next+1;
					}
					else dp[index][rest] = Math.min(p1, p2Next+1);
				}
			}
		}
		return dp[0][aim];
		
	}

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

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

相关文章

交通感知与车路协同系统-计算机毕设Java|springboot实战项目

&#x1f34a;作者&#xff1a;计算机毕设残哥 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目、 源…

PHP—MySQL(PHP连接数据库)

目录 【学习目标、重难点知识】 【学习目标】 【重难点知识】 二、PHP 和 MySQL 的合作方式 三、PHP连接数据库 3.1、MySQLi拓展 ​编辑 3.2、建立与数据库的连接 &#xff08;4&#xff09;创建SQL语句 &#xff08;5&#xff09;获取结果 &#xff08;6&#xff09…

STM32(二):GPIO

GPIO(General Purpose Input Output)通用输入输出口 1.可配置为8种输入输出模式&#xff0c;引脚电平:0V~3.3V&#xff0c;部分引脚可容忍5V&#xff0c;输出模式下可控制端口输出高低电平&#xff0c;用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等&#xff0c;输入模式下…

在vscode使用markdown格式、自动补齐、以及快捷键

在扩展中搜索markdown all in one&#xff0c;下载使用即可。

人工智能在网络安全中的三大支柱

人工智能 (AI) 席卷了网络安全行业&#xff0c;各种供应商都在努力将 AI 融入其解决方案中。但 AI 与安全之间的关系不仅仅在于实现 AI 功能&#xff0c;还在于攻击者和防御者如何利用该技术改变现代威胁形势。它还涉及如何开发、更新和保护这些 AI 模型。如今&#xff0c;网络…

【qt】基于tcp的服务端编写

实现服务端&#xff0c;连接后拿到客户端ip地址和端口号 ui设计 修改对应行编辑对象名&#xff0c;修改客户端ip为clientip,客户端端口号为clientport 代码实现 1.网络通信需要加network 2.包含头文件 3.定义一个QTcpserver变量&#xff0c;并初始化 4.服务端监听&#…

字符串String概述,遍历字符串

String的注意点 字符串的内容是不会发生改变的&#xff0c;它的对象在创建后不能被更改 string是Java定义好的一个类&#xff0c;定义在java.long包中&#xff0c;所以使用的时候不需要导入包。 Java程序中的所有字符串文字&#xff08;例如“abcdefg”&#xff09;&#xf…

【Go语言初探】(二)、项目文件结构和GOPATH设置

一、go语言项目文件结构 由go/bin、go/src和go/pkg三个子文件夹组成&#xff0c;见下图&#xff1a; 实际项目&#xff1a; 二、gopath路径变量设置 在项目中创建main.go文件后&#xff0c;IDE会提示设置GOPATH路径&#xff1a; 点击“configure GOPATH”&#xff0c;设置GOP…

酒项目加密封装步骤;linux查看IP地址,查看MAC地址, 查看CPU序列号

线上酒项目为例 目录 线上酒项目为例 第一步 第二步 linux查看IP地址 查看MAC地址 方法1: 方法2: 方法3&#xff1a; 查看CPU序列号 为什么不用物理机的不同虚拟机的cpu序列号是相同&#xff0c;给我们的各个系统都是相同的 第一步 在maven模块分层上进行加密&#x…

15:【stm32】时钟树

时钟树 1、时钟树1.1&#xff1a;简要的介绍1.2&#xff1a;基本结构1.2.1&#xff1a;stm32的内部结构1.2.2&#xff1a;树的关键节点1.2.3&#xff1a;系统时钟的来源 2、RCC标准库编程2.1&#xff1a;片上外设的复位与释放2.2&#xff1a;时钟系统配置2.3&#xff1a;时钟树…

算法:DFS之记忆化搜索

目录 记忆化搜索 题目一&#xff1a;不同路径 题目二&#xff1a;最长递增子序列 题目三&#xff1a;猜数字大小II 题目四&#xff1a;矩阵中的最长递增路径 记忆化搜索 说到记忆化搜索&#xff0c;首先就需要引入斐波那契数这道题&#xff0c;非常经典&#xff0c;可以很…

第44课 Scratch入门篇:无限画中画

无限画中画 故事背景: 无止境的显示一幅画。 程序原理: 利用多张基本一样的图,不停循环显示,产生视觉上的错觉,原理很简单,只是一种实现方式而已。 开始编程 1、删除预设的猫咪角色,上传以后在那个无限循环的图片,大小为 480*360 2、接下来复制造型,使用选择工具…

.net 8.0 下 Blazor 通过 SignalR 与 Winform 交互

定义一个Hub using Microsoft.AspNetCore.SignalR;namespace Beatrane.Connect.Blazor {public class DeviceHub : Hub{public async Task SendMessage(string user, string message){await Clients.All.SendAsync("ReceiveMessage", user, message);}public async …

静态分析、动态调试与重打包:去除Android APK烦人广告

最近&#xff0c;一直使用的某款APP&#xff0c;广告越来越多&#xff0c;更令人发指的是&#xff0c;广告弹框最后都变成无法关闭的形式&#xff0c;不使用会员压根没法正常使用。应用市场广大用户的评论说出了我们的心声。 虽说充会员可以免广告&#xff0c;这点小钱&#xf…

《python语言程序设计》2018版第7章第7题代数2x2线性方程式设计一个名为LinearEquation

#大家可以看一下 两道题的内容 第n次刷第4章第3题的代码。朝纲用来函数的概念 def judge_num(a, b, c, d):return (a * d) - (b * c)def run_cont(a, b, c, d, e, f):cc judge_num(a, b, c, d)if cc 0:print("The equation has no solution")else:x ((e * d) - (…

苹果手机怎么清理重复照片的解决方案

随着智能手机摄像头技术的飞速发展&#xff0c;我们越来越依赖iPhone来记录生活中的点点滴滴。不可避免地&#xff0c;这也导致了大量重复照片的产生&#xff0c;这些重复照片不仅占用了宝贵的存储空间&#xff0c;还使得照片库显得混乱无序。本文将介绍苹果手机怎么清理重复照…

微信小程序开发的强大助力:HTTP 虚拟专线

​编辑 一、微信小程序开发的热潮与挑战 二、HTTP 虚拟专线的引入 三、HTTP 虚拟专线的关键功能 &#xff08;一&#xff09;用于回调 &#xff08;二&#xff09;助力运维 四、HTTP 虚拟专线的技术优势 &#xff08;一&#xff09;80 和 443 端口的灵活访问 &#xff0…

测试架构师技能修炼---关系化透明

目录 一、该信任时就给别人信任 二、你说的话长久不变 三、道歉表明你的透明化 四、学会在做出反应前倾听 五、允许别人对你透明化 它涉及与别人之间的关系应保持透明化&#xff0c;包括给别人信任&#xff1b;持续给别人传递一致的消息&#xff1b;向别人道歉&#xff1b…

[SDK]-键盘消息和鼠标消息

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解键盘消息和鼠标消息&#xff0c;下一节讲解控件的相关知识点 键盘消息 应用程序从windows接收的关于键盘事件的消息分为击键和字符两种windows再发送击键消息的同时 还会发送字符消息Shift、ctrl、alt…

【C++】string讲解

一、string的理解 我们可以把string看作一个更高级用类实现的char* 。或者直接叫他字符串类型&#xff0c;一听就是定义字符串的。 二、string的使用 用法就和int、char 类型一样&#xff0c;而且功能比他们强大很多。 三、string的功能 只列举常用功能 1、通过“[]”访问…