【17】暴力递归改dp(下)

news2024/9/25 9:40:10

目录

一.两人玩游戏

二.象棋游戏

三.鲍勃存活

四.凑钱方案数问题


一.两人玩游戏

 题目:有一个正整数数组,A和B两个人轮流拿数组的最左或最右的数值,返回最终的最高分数。

暴力递归版本 

	public static int win1(int[] arr) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		// 0.。N-1范围上,先手获得最优分和后手获得最优分,返回较大的
		return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1));
	}	

    // 先手函数
	// 当前该你拿,arr[i..j]
	// 返回你的最好分数
	public static int f(int[] arr, int i, int j) {
		if (i == j) {
			return arr[i];
		}
		// i..j
		return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));
	}

	// 后手函数
	// 当前步该你拿,是对方在arr[i..j]范围上拿
	// 返回你的最好分数
	public static int s(int[] arr, int i, int j) {
		if (i == j) {
			return 0;
		}
		// i..j 我在哪个范围选数,是由对手决定的,对手一定会将较少的留给你
		return Math.min(f(arr, i + 1, j), f(arr, i, j - 1));
	}

记忆化搜索版本

	public static int win1(int[] arr) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		int[][] fdp=new int[arr.length][arr.length];
		int[][] sdp=new int[arr.length][arr.length];
		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr.length;j++) {
				fdp[i][j]=-1;
				sdp[i][j]=-1;
			}
		}
		// 0.。N-1范围上,先手获得最优分和后手获得最优分,返回较大的
		return Math.max(f(arr, 0, arr.length - 1, fdp, sdp), s(arr, 0, arr.length - 1, fdp, sdp));
	}

	// 先手函数
	// 当前该你拿,arr[i..j]
	// 返回你的最好分数
	public static int f(int[] arr, int i, int j, int[][] fdp, int[][] sdp) {
		if (i == j) {
			return arr[i];
		}
		if(fdp[i][j]!=-1) {
			return fdp[i][j];
		}
		// i..j
		fdp[i][j]=Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));
		return fdp[i][j];
	}

	// 后手函数
	// 当前步该你拿,是对方在arr[i..j]范围上拿
	// 返回你的最好分数
	public static int s(int[] arr, int i, int j, int[][] fdp, int[][] sdp) {
		if (i == j) {
			return 0;
		}
		if(sdp[i][j]!=-1) {
			return sdp[i][j];
		}
		// i..j 我在哪个范围选数,是由对手决定的,对手一定会将较少的留给你
		sdp[i][j]=Math.min(f(arr, i + 1, j), f(arr, i, j - 1));
		return sdp[i][j];
	}

动态规划版本

每个位置都依赖于该位置左侧和下侧一个格子。所以这里可以按照对角线交替求解。

	public static int win2(int[] arr) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		int[][] f = new int[arr.length][arr.length];
		int[][] s = new int[arr.length][arr.length];
		for (int j = 0; j < arr.length; j++) {
			f[j][j] = arr[j];
			for (int i = j - 1; i >= 0; i--) {
				f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]);
				s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]);
			}
		}
		return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]);
	}

关键点:把图画出来,标出base case,找出一般位置的依赖关系。

二.象棋游戏

题目:马起始位于(0,0)位置,随后给出目标位置(x, y),要求马必须走k步到达目标位置,问从起始到达目标方案数

暴力递归版本 

	public static int getWays(int x, int y, int step) {
		return process(x, y, step);
	}

	// 潜台词:从(0, 0)位置出发
	// 要去往(x, y)位置,必须跳step步
	// 返回方法数
	public static int process(int x, int y, int step) {
		// 越界判断,有多少种到达越界位置,0种方法
		if (x < 0 || x > 8 || y < 0 || y > 9) {
			return 0; 
		}
		// 已经跳完了,不能动了
		if (step == 0) {
			return (x == 0 && y == 0) ? 1 : 0;
		}
		// 要到达的位置不越界,也有步数可以跳
		return process(x - 1, y + 2, step - 1)
				+ process(x + 1, y + 2, step - 1)
				+ process(x + 2, y + 1, step - 1)
				+ process(x + 2, y - 1, step - 1)
				+ process(x + 1, y - 2, step - 1)
				+ process(x - 1, y - 2, step - 1)
				+ process(x - 2, y - 1, step - 1)
				+ process(x - 2, y + 1, step - 1);
	}

动态规划版本

	public static int dpWays(int x, int y, int step) {
		if (x < 0 || x > 8 || y < 0 || y > 9 || step < 0) {
			return 0;
		}
		int[][][] dp = new int[9][10][step + 1];
		dp[0][0][0] = 1;
		for (int h = 1; h <= step; h++) {
			for (int r = 0; r < 9; r++) {
				for (int c = 0; c < 10; c++) {
					dp[r][c][h] += getValue(dp, r - 1, c + 2, h - 1);
					dp[r][c][h] += getValue(dp, r + 1, c + 2, h - 1);
					dp[r][c][h] += getValue(dp, r + 2, c + 1, h - 1);
					dp[r][c][h] += getValue(dp, r + 2, c - 1, h - 1);
					dp[r][c][h] += getValue(dp, r + 1, c - 2, h - 1);
					dp[r][c][h] += getValue(dp, r - 1, c - 2, h - 1);
					dp[r][c][h] += getValue(dp, r - 2, c - 1, h - 1);
					dp[r][c][h] += getValue(dp, r - 2, c + 1, h - 1);
				}
			}
		}
		return dp[x][y][step];
	}

	public static int getValue(int[][][] dp, int row, int col, int step) {
		if (row < 0 || row > 8 || col < 0 || col > 9) {
			return 0;
		}
		return dp[row][col][step];
	}

三.鲍勃存活

问题:有一个大小为N*M的网格,给出鲍勃的起始位置(a,b),鲍勃必须走K步,求鲍勃活下来的概率(不越界)。

4^k就是Bob走K步的所有情况,所以概率就是用生存的( 方法数/4^k )

暴力递归版本

	public static String bob1(int N, int M, int i, int j, int K) {
		long all = (long) Math.pow(4, K);
		long live = process(N, M, i, j, K);
		long gcd = gcd(all, live);
		return String.valueOf((live / gcd) + "/" + (all / gcd));
	}

	// N*M的区域,Bob从(row,col)位置出发,走rest步之后,获得的生存方法数
	public static long process(int N, int M, int row, int col, int rest) {
		if (row < 0 || row == N || col < 0 || col == M) {
			return 0;
		}
		// row, col没越界
		if (rest == 0) {
			return 1;
		}
		// 还没走完,row, col也没有越界
		long live = process(N, M, row - 1, col, rest - 1);
		live += process(N, M, row + 1, col, rest - 1);
		live += process(N, M, row, col - 1, rest - 1);
		live += process(N, M, row, col + 1, rest - 1);
		return live;
	}

	public static long gcd(long m, long n) {
		return n == 0 ? m : gcd(n, m % n);
	}

记忆化、动态规划套路一样。。。

四.凑钱方案数问题

题目:有一个无重复元素的正整数数组,里面的元素可以重复使用任意次,给定一个目标面值aim,求达到目标aim的组合方法数。

暴力递归版本 

	// arr里都是正数,没有重复值,每一个值代表一种货币,每一种货币可以使用无限张
	// 最终要找的零钱数就是aim
	// 找零方法数返回
	public static int way1(int[] arr, int aim) {
		return process(arr, 0, aim);
	}
	
	// 可以自由使用arr[index...]所有的面值
	// 需要搞定的钱数是rest
	// 返回找零的方法数
	public static int process(int[] arr, int index, int rest) {
		if(index==arr.length) {
			return rest==0?1:0;
		}
		// arr[index] 0张 1张 ... 不要超过rest的钱数
		int ways=0;
		for(int zhang=0;arr[index]*zhang<=rest;zhang++) {
			ways+=process(arr, index+1, rest-arr[index]*zhang);
		}
		return ways;
	}

 动态规划版本

public static int way2(int[] arr, int aim) {
		if(arr==null||arr.length==0)){
			return 0;
		}
		int[][] dp=new int[arr.length+1][aim+1];
		dp[arr.length][0]=1;
		for(int index=arr.length-1;index>=0;index--) {
			for(int rest=0;rest<=aim;rest++) {
				int ways=0;
				for(int zhang=0;arr[index]*zhang<=rest;zhang++) {
					ways+=dp[index+1][rest-arr[index]*zhang];
				}
				dp[index][rest] = ways;
			}
		}
		return dp[0][aim];
	}

上面第三层的循环可以进行优化

? = a + b + c + ...   

X = b + c + ...

=>  ? = X + a

	public static int way2(int[] arr, int aim) {
		if(arr==null||arr.length==0)){
			return 0;
		}
		int[][] dp=new int[arr.length+1][aim+1];
		dp[arr.length][0]=1;
		for(int index=arr.length-1;index>=0;index--) {
			for(int rest=0;rest<=aim;rest++) {
				dp[index][rest]=dp[index+1][rest];
				if(rest-arr[index]>=0) {
					dp[index][rest]+=dp[index][rest-arr[index]];
				}
			}
		}
		return dp[0][aim];
	}

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

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

相关文章

Chat App 项目之解析(三)

Chat App 项目介绍与解析&#xff08;一&#xff09;-CSDN博客文章浏览阅读76次。Chat App 是一个实时聊天应用程序&#xff0c;旨在为用户提供一个简单、直观的聊天平台。该应用程序不仅支持普通用户的注册和登录&#xff0c;还提供了管理员登录功能&#xff0c;以便管理员可以…

webflux源码解析(1)-主流程

目录 1.关键实例的创建1.1 实例创建1.2 初始化 2.处理请求的关键流程2.1 从ReactorHttpHandlerAdapter开始2.1 DispatcherHandler的初始化2.2查找mapping handler2.3 处理请求(执行handler)2.4 返回结果处理 3.webflux的配置装配参考&#xff1a; WebFlux是Spring 5.0框架推出的…

算法的学习笔记—对称的二叉树(牛客)

&#x1f600;前言 在算法的世界中&#xff0c;二叉树是一个极其重要的数据结构。它不仅广泛应用于各种算法的设计中&#xff0c;也是面试中常见的考察点之一。今天&#xff0c;我们将深入探讨一个经典的二叉树问题——对称的二叉树&#xff0c;并且会展示如何通过Java代码来解…

趋动VAICP技术认证全球考试正式上线

8月18日&#xff0c;趋动科技主办的VAICP(VirtAl Certified Professional) Al算力池化专家认证考试正式在 Pearson VUE上线。 即日起&#xff0c;凡参加过VAICP培训的学员&#xff0c;可立即通过Pearson VUE官网注册参加考试&#xff0c;官网链接&#xff1a;https://home.pea…

是肯定,更是动力 | 一封封感谢信纷至沓来,全视通服务获赞誉

在全视通的故事里&#xff0c;有那么一群人&#xff0c;他们穿梭于全国各地&#xff0c;奔波于各种交付调试、维检。山河湖海&#xff0c;严寒酷暑&#xff0c;从晨曦至夜幕&#xff0c;他们只为兑现那份让客户更加满意的承诺。他们是使命必达的守护者——全视通服务团队。他们…

串口UART

常见通信接口 串口定义 串口定义&#xff1a; 通用串行异步收发器 通用&#xff1a;UART的应用非常广泛&#xff0c;应用领域&#xff1a;工控行业&#xff0c;电力系统等串行&#xff1a;处理器和外设之间只需连接一根信号线&#xff0c;处理器和外设数据传输是一个bit位一…

CORS跨域问题全解:原理、问题与解决方案

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

【Qt】QDesigner 源码 控件图片资源路径

qttools-5.12.12-designer-1\qttools-5.12.12-designer\qttools-5.12.12\src\designer\src\components\formeditor\images\win qttools-5.12.12-designer-1\qttools-5.12.12-designer\qttools-5.12.12\src\designer\src\components\formeditor\images\widgets

docker部署drawio

1&#xff09;介绍Drawio.io GitHub&#xff1a;GitHub - jgraph/drawio: draw.io is a JavaScript, client-side editor for general diagramming. Draw.io是一款开源的绘制流程图的工具&#xff0c;拥有大量免费素材和模板。程序本身支持中文在内的多国语言&#xff0c;创建…

【源码+文档+调试讲解】健美操评分系统

摘 要 健美操评分系统采用B/S架构&#xff0c;数据库是MySQL。系统的搭建与开发采用了先进的JAVA进行编写&#xff0c;使用了springboot框架。该系统从三个对象&#xff1a;由管理员、裁判员和用户来对系统进行设计构建。主要功能包括首页&#xff0c;个人中心&#xff0c;裁判…

2024潜力市场:工商业屋顶光伏项目开发!

随着全球对可再生能源的日益重视和“双碳”目标的持续推进&#xff0c;工商业屋顶光伏项目作为分布式光伏的主要类型之一&#xff0c;正迎来前所未有的发展机遇。 一、技术成熟度与成本降低 近年来&#xff0c;光伏技术的飞速发展显著提升了光伏组件的转换效率&#xff0c;并降…

记git仓库由局域网迁移到外网

项目管理平台&#xff1a;gitlab 一台云主机 流程&#xff1a; 1.外网机器上搭建gitlab 2.项目网站上新建空白项目 3.本机就项目切换到主分支&#xff0c;切换源&#xff1a;git remote set-url origin http://x.x.x.x:yyy/zzzz/new.git 4.登陆新平台的账号&#xff0c;使…

【吸引力法则】探究人生欲:追求深度体验与宇宙链接

文章目录 什么是人生欲&#xff1f;唤醒人生欲&#xff1a;克服配得感的三大障碍1 第一大障碍&#xff1a;法执的压制2 第二大障碍&#xff1a;家庭的继承2.1 家庭创伤的代际传递2.2 家庭文化基因的传递2.2.1 “成年人最大的美德是让自己的生活过得更加精彩。”2.2.2 荷欧波诺波…

【数据分享】1999—2022年地级市地区生产总值及一二三产构成数据(Shp/Excel格式)

在之前的文章中&#xff0c;我们分享过基于2000-2023年《中国城市统计年鉴》整理的1999-2022年地级市的人口相关数据、各类用地面积数据、污染物排放和环境治理相关数据、房地产投资情况和商品房销售面积、社会消费品零售总额和年末金融机构存贷款余额、一般公共预算收支状况、…

第二十三节、血量更新逻辑的实现

一、创建代码 引入命名空间 using UnityEngine.UI; 调用UI必须有这个代码 二、ScriptObject类 1、是一个持久化存储文件的类型 接收所有的事件方法 先继承SO类&#xff0c;然后创建项目菜单 2、进行订阅 放入事件类&#xff0c;关联代码&#xff0c;即可进行广播 传递给这…

【什么是依赖倒置原则?】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

还原source insight4.0的工具栏

工具栏消失了一部分 要还原 Source Insight 工具栏&#xff0c;可以按照以下步骤操作&#xff1a; 打开 Source Insight。在菜单栏中选择 "View"&#xff08;视图&#xff09;。在下拉菜单中选择 "Toolbars"&#xff08;工具栏&#xff09;。在弹出的子菜…

聊聊对神经网络的基础理解

这是鼎叔的第一百零六篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 欢迎关注本专栏和微信公众号《敏捷测试转型》&#xff0c;星标收藏&#xff0c;大量原创思考文章陆续推出。本人新书《无测试组织-测试团队的敏捷转型》已出版&#xff08;机械工业出版社…

GIS中AI矢量化工具

减少矢量化中86%工作量的AI工具 最近我在X平台有注意到一个矢量化工具&#xff0c;AI Vectorizer &#xff0c;根据实验对比&#xff0c;这个AI工具可以减少在矢量化过程中86%的鼠标点击数&#xff0c;极大地减少矢量化过程中的工作量。 AI Vectorizer 需要通过网络交互&#…

【HarmonyOS NEXT星河版开发学习】综合测试案例-各平台评论部分

目录 前言 功能展示 整体页面布局 最新和最热 写评论 点赞功能 界面构建 初始数据的准备 列表项部分的渲染 底部区域 index部分 知识点概述 List组件 List组件简介 ListItem组件详解 ListItemGroup组件介绍 ForEach循环渲染 列表分割线设置 列表排列方向设…