当前位置: 首页 > news >正文

算法笔记(四)从暴力递归到动态规划


layout: post
title: 算法笔记(四)从暴力递归到动态规划
description: 算法笔记(四)从暴力递归到动态规划
tag: 算法


文章目录

  • 机器人路径数
    • 暴力递归
    • memo表记忆搜索
    • 动态规划
  • 组成目标最少需要几枚硬币
    • 暴力递归

机器人路径数

【题目】给定一个数N代表从1~N有N个位置,在起始位置1处只能往后走,结尾位置N处只能往前走,再给定机器人初始位置S和需要前往的位置E,如果规定必须在K步从S到达E,有多少种路径选择?

暴力递归

暴力递归的方法就是每次来到某个位置,尝试所有可以走的路,直至剩余步数为0.

int forceRecurRobotPath(int N, int E, int rest , int cur) {
	// 当恰好走,返回当前位置是否为E,是则找到一条路
	if (rest == 0) {
		return cur == E ? 1 : 0;
	}
	// 当来到1处只能往后走
	if (cur == 1) {
		return forceRecurRobotPath(N, E, rest - 1, cur + 1);
	}
	// 当来到N处只能往前走
	if (cur == N) {
		return forceRecurRobotPath(N, E, rest - 1, cur - 1);
	}
	// 中间位置既可以往前也可以往后
	return forceRecurRobotPath(N, E, rest - 1, cur + 1) + (N, E, rest - 1, cur - 1);
}

int robotPath1(int N, int E, int K, int S) {
	return forceRecurRobotPath(N, E, K, S);
}

memo表记忆搜索

上边暴力递归只有两个可变参数rest和cur,
这样暴力递归会重复计算很多之前计算过的过程。那么一个改进的思路就是以空间换时间,记录下每个可变参数的组合的计算结果到表中,每次如果遇到表中已有组合即可直接调用,称为记忆化搜索版本递归
在这里插入图片描述
按照这种思路,写出带记忆搜索的递归:
构建一个二维数组memo表,将可变参数rest和cur的所有组合找到的可行路径数都记录下:
rest的取值范围为[0, K],cur的取值范围为[1,N]
vector<vector<int>> memo(N + 1, vector<int>(K + 1, -1));

// 带备忘录的递归
int memoRecurRobotPath(int N, int E, int rest, int cur, vector<vector<int>> memo) {
	if (memo[rest][cur] != -1) {
		return memo[rest][cur];
	}
	// 当恰好走完,返回当前位置是否为E,是则找到一条路
	if (rest == 0) {
		memo[rest][cur] = cur == E ? 1 : 0;
	}
	// 当来到1处只能往后走
	else if (cur == 1) {
		memo[rest][cur] = memoRecurRobotPath(N, E, rest - 1, cur + 1, memo);
	}
	// 当来到N处只能往前走
	else if (cur == N) {
		memo[rest][cur] = memoRecurRobotPath(N, E, rest - 1, cur - 1, memo);
	}
	else
	{
		// 中间位置既可以往前也可以往后
		memo[rest][cur] = memoRecurRobotPath(N, E, rest - 1, cur + 1, memo) + memoRecurRobotPath(N, E, rest - 1, cur - 1, memo);
	}
	return memo[rest][cur];
}
int robotPath2(int N, int E, int K, int S) {
	vector<vector<int>> memo(N + 1, vector<int>(K + 1, -1));
	return memoRecurRobotPath(N, E, K, S, memo);
}

动态规划

如果memo表结构数据之间有严格的依赖关系,那么可以将他改为动态规划的形式。
如下图,从递归过程上看,首先rest为0时,只有cur = 4(E),位置找到一种路径,红色框是出口位置。当cur来到1,它只能往后走,路径数依赖于f(rest - 1, cur + 1),即它在memo表中右上方的结果,cur来到N,只能往前走,路径数依赖于f(rest-1,cur-1),即它在memo表中左上方的结果,而当cur在中间位置时,它依赖于f(rest-1,cur-1)+ f(rest-1,cur+1),左上+右上。由此,表中所有数据其实都可以由已经解计算出来,这是一种严格表结构。动态规划的过程就是,直接根据严格表的依赖关系,从表中已有解,一步一步得到全部的解,而所求必在表中。
在这里插入图片描述
动态规划版本:

int dpRobotPath(int N, int E, int K, int S) {
	vector<vector<int>> memo(K + 1, vector<int>(N + 1, -1));
	// rest = 0(when row = 0:) 先全赋值0, i = 0位置都-1,弃用
	for (int i = 1; i < N + 1; i++) {
		memo[0][i] = 0;
	}
	// 再将出口即终点处赋值为1
	memo[0][E] = 1;
	for (int rest = 1; rest <= K; rest++) {
		for (int cur = 1; cur <= N; cur++) {
			if (cur == 1) {
				memo[rest][cur] = memo[rest - 1][2];
			}
			else if(cur == N) {
				memo[rest][cur] = memo[rest - 1][N - 1];
			}
			else {
				memo[rest][cur] = memo[rest - 1][cur - 1] + memo[rest - 1][cur + 1];
			}
		}
	}
	return memo[K][S];
}

组成目标最少需要几枚硬币

【题目】给定正数数组,每个值代表一个硬币的币值,给定目标值target,问最少需要几枚硬币可以组成target。

暴力递归

每个硬币选或不选两种可能,这就可以列出所有的硬币的选择组合,将所有可以达成target的组合进行对比,选取硬币最少的组合。

相关文章:

  • golang设计模式——行为模式
  • springboot版HelloWorld
  • 在portacle中获取EMACS Lisp帮助文档的方法(Win11)
  • 线性代数学习笔记8-1:复数矩阵与Hermite矩阵、酉矩阵、傅里叶矩阵和快速傅里叶变换FFT
  • java ssm创意设计分享系统
  • ABAP Debug 调试功能
  • 【PAT甲级】1124 Raffle for Weibo Followers
  • 数组 vector
  • JAVA中的进制与位运算
  • C++怎么判断windows系统是64位还是32位
  • 位图,布隆过滤器的原理和实现
  • java医用物资信息管理系统 ssm
  • 【ELFK】之消息队列kafka
  • 【PAT甲级】1153 Decode Registration Card of PAT
  • 五、JAVA基本数据类型
  • Docker容器管理
  • java8 Stream Pipelines 浅析
  • Javascript 原型链
  • JavaScript实现分页效果
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • node学习系列之简单文件上传
  • npx命令介绍
  • Protobuf3语言指南
  • swift基础之_对象 实例方法 对象方法。
  • vue 个人积累(使用工具,组件)
  • Vue.js源码(2):初探List Rendering
  • Vultr 教程目录
  • 闭包--闭包之tab栏切换(四)
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 时间复杂度与空间复杂度分析
  • 小程序开发中的那些坑
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 阿里云移动端播放器高级功能介绍
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • 昨天1024程序员节,我故意写了个死循环~
  • ​如何在iOS手机上查看应用日志
  • ​油烟净化器电源安全,保障健康餐饮生活
  • # 安徽锐锋科技IDMS系统简介
  • (145)光线追踪距离场柔和阴影
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .gitignore文件_Git:.gitignore
  • .NET Project Open Day(2011.11.13)
  • .Net Remoting常用部署结构
  • .NET 反射 Reflect
  • .NET6实现破解Modbus poll点表配置文件
  • .Net多线程总结
  • .net分布式压力测试工具(Beetle.DT)
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧
  • [.net] 如何在mail的加入正文显示图片
  • [1525]字符统计2 (哈希)SDUT