动态规划求二维网格中从左上角到右下角的最短路径( 每次只能向下、向右、向右下走 ) java 实现

dp[i][j] 表示在以点(0,0)作为左上角,点(i,i) 作为右下角的二维网格中 左上角到右下角的最短路径,
动态转移方程为:dp[i][j] = min{ dp[i][j-1],dp[i-1][j],dp[i-1][j-1] }.distance + weight[i][j]

ImageUtils.java:

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import javax.imageio.ImageIO;public class ImageUtils {/**** @param mat* @param outputPath* @param cellSize 格子的边长*/public static void printMat2Image(int[][] mat, String outputPath,int cellSize,PathVO path) {// 总行数int rowCount = mat.length;// 总列数int colCount = mat[0].length;int fontSize = cellSize / 2;BufferedImage image = new BufferedImage(colCount * cellSize, rowCount * cellSize, BufferedImage.TYPE_INT_RGB);Graphics g = image.getGraphics();Random random = new Random();// 设置背景色为白色g.setColor(Color.WHITE);g.fillRect(0, 0, colCount * cellSize, rowCount * cellSize);// 画网格g.setColor(Color.BLACK);for (int i = 0; i <= rowCount; i++) {g.drawLine(0, i * cellSize, colCount * cellSize, i * cellSize);}for (int i = 0; i <= colCount; i++) {g.drawLine(i * cellSize, 0, i * cellSize, rowCount * cellSize);}Set<String> codes = new HashSet<>();List<PointVO> points = path.getPoints();for( PointVO point:points ){codes.add( point.getRowNum() + "_" + point.getColNum() );}/*   Color color = g.getColor();// 画路径List<PointVO> points = path.getPoints();g.setColor( Color.GREEN );for( PointVO point:points ){int x = point.getRowNum() * cellSize;int y = point.getColNum() * cellSize;g.fillRect(x, y, cellSize, cellSize); // 填充矩形}g.setColor( color );*/// 写入文本g.setFont(new Font("Arial", Font.BOLD, fontSize));Color color_old = g.getColor();Color color_green = Color.GREEN;FontMetrics fontMetrics = g.getFontMetrics();for (int rowNum = 0; rowNum < rowCount; rowNum++) {int[] row = mat[rowNum];for (int colNum = 0; colNum < colCount; colNum++) {int num = row[colNum];String code = rowNum + "_" + colNum;if( codes.contains( code ) ){g.setColor( color_green );}else {g.setColor( color_old );}String text = String.valueOf( num );int x = colNum * cellSize + (cellSize - fontMetrics.stringWidth(text) ) / 2;int y = rowNum * cellSize + (cellSize - fontMetrics.getHeight()) / 2 + fontMetrics.getAscent();g.drawString(text, x, y);}}// 输出图片try {ImageIO.write(image, "png", new File(outputPath));System.out.println("图片已生成:" + outputPath);} catch (IOException e) {e.printStackTrace();}}
}

PathVO.java:
import lombok.Getter;
import lombok.Setter;import java.io.Serializable;
import java.util.List;@Getter
@Setter
public class PathVO implements Serializable {private List<PointVO> points;private Integer distance;}

PointVO.java:
import lombok.Getter;
import lombok.Setter;import java.io.Serializable;@Getter
@Setter
public class PointVO implements Serializable {private Integer rowNum;private Integer colNum;public PointVO(Integer rowNum, Integer colNum) {this.rowNum = rowNum;this.colNum = colNum;}
}

Test.java:
import lombok.Getter;
import lombok.Setter;import java.util.ArrayList;
import java.util.List;
import java.util.Random;@Getter
@Setter
public class Test   {public static void main(String[] args) {test();}private static void test(){/*   int rowCount = 10;int colCount = 10;*/// int[][] mat = initRandomWeightMat( rowCount,colCount );int[][] mat = new int[][]{{ 9, 9, 9, 9, 9, 9 },{ 9, 1, 9, 9, 9, 9 },{ 9, 1, 1, 9, 9, 9 },{ 9, 1, 9, 1, 9, 9 },{ 9, 1, 1, 1, 9, 1 },{ 9, 9, 9, 9, 1, 9 }};// dp[i][j] 表示在以点(0,0)作为左上角,点(i,i) 作为右下角的二维网格中 左上角到右下角的最短路径,// 动态转移方程为:dp[i][j] = min{ dp[i][j-1],dp[i-1][j] }.distance + weight[i][j]int rowCount = mat.length;int colCount = mat[0].length;PathVO[][] dp = new PathVO[rowCount][colCount];PathVO path = new PathVO();List<PointVO> points = new ArrayList<>();points.add( new PointVO( 0,0 ) );path.setPoints( points );path.setDistance( mat[0][0] );dp[0][0] = path;for (int colNum = 1; colNum < colCount; colNum++) {int rowNum = 0;int weight = mat[rowNum][colNum];PathVO path_prev = dp[rowNum][colNum - 1];path = new PathVO();points = new ArrayList<>();points.addAll( path_prev.getPoints() );points.add( new PointVO( rowNum,colNum ) );path.setPoints( points );path.setDistance( path_prev.getDistance() + weight );dp[rowNum][colNum] = path;}for (int rowNum = 1; rowNum < rowCount; rowNum++) {int colNum = 0;int weight = mat[rowNum][colNum];PathVO path_prev = dp[rowNum-1][colNum];path = new PathVO();points = new ArrayList<>();points.addAll( path_prev.getPoints() );points.add( new PointVO( rowNum,colNum ) );path.setPoints( points );path.setDistance( path_prev.getDistance() + weight );dp[rowNum][colNum] = path;}for (int rowNum = 1; rowNum < rowCount; rowNum++) {for (int colNum = 1; colNum < colCount; colNum++) {Integer weight = mat[ rowNum ][colNum];path = new PathVO();points = new ArrayList<>();// 当前点要么从上面的点到达,要么从 左边的点到达PathVO path_prev_up = dp[ rowNum -1 ][colNum];PathVO path_prev_left = dp[ rowNum ][colNum-1];PathVO path_prev_left_up = dp[ rowNum-1 ][colNum-1];PathVO path_prev_min = path_prev_up;if( path_prev_left.getDistance() < path_prev_min.getDistance() ){path_prev_min = path_prev_left;}if( path_prev_left_up.getDistance() < path_prev_min.getDistance() ){path_prev_min = path_prev_left_up;}points.addAll( path_prev_min.getPoints() );points.add( new PointVO( rowNum,colNum ) );path.setDistance( path_prev_min.getDistance() +  weight );path.setPoints( points );dp[ rowNum ][colNum] = path;}}path = dp[ rowCount -1 ][colCount -1];String outputPath = "C:\\E\\xxx.png";ImageUtils.printMat2Image( mat,outputPath,40,path );}private static int[][] initRandomWeightMat(int rowCount, int colCount) {Random random = new Random();// 初始化 二维网格矩阵int[][] mat = new int[rowCount][colCount];for (int rowNum = 0; rowNum < rowCount; rowNum++) {for (int colNum = 0; colNum < colCount; colNum++) {mat[ rowNum ][colNum] = random.nextInt( 2 ) + 1;}}return mat;}
}

测试输出:

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

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

相关文章

三十分钟学会Shell(上)

Shell ​ Shell 本身并不是内核的一部分&#xff0c;它只是站在内核的基础上编写的一个应用程序&#xff0c;是用户和Linux文件系统之间的桥梁。Shell 有自己的特殊性&#xff0c;就是开机立马启动&#xff0c;并呈现在用户面前&#xff1b;用户通过 Shell 来使用 Linux&#x…

Windows日常故障自我排查:用工具eventvwr.msc(事件查看器)分析问题故障

windows故障排查方法一&#xff1a; 工具用法 系统故障问题时&#xff0c;找不到解决方法 首先&#xff0c; 在搜索栏输入&#xff1a; 事件查看器(eventvwr.msc) 打开程序 根据程序找到程序运行的LOG 根据程序Operational筛选出错误日志&#xff1a; 日志中找错误原因&…

假期宅家不无聊,用极米投影仪H6 Pro 4K解锁宅家多样玩法

不知道大家平时的假期是怎么度过的&#xff0c;是选择出门游玩?还是要在家好好安排自己的学习充电计划?平日工作这么累&#xff0c;不如趁假期好好休息一下&#xff0c;把以前落下的番剧补回来。不过手机的屏幕太小&#xff0c;电脑又不能躺在床上看&#xff0c;只有够大尺寸…

Lora学习资料汇总

目录 LoRa联盟 Semtech lora网关供应商: LoRaMAC API文档 论坛 开发板 主流技术对比分析 LoRa网络距离模拟测试方法 LoRa应用 Lora LoraWAN教程 LoRa联盟 LoRa联盟&#xff1a;LoRaWAN规范的制定组织 https://www.lora-alliance.org/ LoRa技术白皮书&#xff1a;htt…

解决mv3版本浏览器插件,不能注入js脚本问题

文章目录 背景引入ifream解决ifream和父页面完全跨域问题参考链接 背景 浏览器插件升级mv3版本后&#xff0c;不能再使用content_script内容脚本向原浏览器&#xff08;top&#xff09;注入script标签达到注入脚本的目的。浏览器认为插入未经审核的脚本是不安全的行为。 引入…

ajax请求方式处理

1、前置准备 1.1、SpringBoot项目下&#xff1a;写一个controller RestController public class TestController {RequestMapping("/yyy")public void test(HttpServletRequest request, HttpServletResponse response){String yang request.getParameter("y…

AI助力钢铁产业数字化,python基于YOLOv5开发构建钢铁产业产品智能自动化检测识别系统

AI为工业产业智能化数字化赋能早已不是什么新鲜事&#xff0c;越来越多的行业和领域开始更大范围去拥抱AI&#xff0c;享受科技带来的变革力量&#xff0c;在我们之前的文章中也有很多相关领域项目的实践经历&#xff0c;本文的核心目标就是想要基于钢铁领域产品数据来开发构建…

【KMP算法】学习总结

说明&#xff1a; 文章内容为对KMP算法的总结&#xff0c;以及力扣例题&#xff1b;文章内容为个人的学习总结&#xff0c;如有错误&#xff0c;欢迎指正。 文章目录 1. KMP算法1.1 算法步骤1.2 关于指针回退问题 2 . LeetCode例题 1. KMP算法 1.1 算法步骤 KMP算法通常用于…

springboot_vue知识点

代码放到了仓库。 springboot_vue知识点 1.搭建1.vue2.springboot 2.前后端请求和响应的封装1.请求封装2.响应封装 3.增删改查1.查询2.分页3.新增和编辑4.删除 4.跨域和自定义异常5.JWT鉴权1.配置pom2.拦截前端请求的拦截器3.生成token并验证token4.登录后生成token5.前端获取…

Grafana如何实现折线柱状图

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

竞赛选题 车位识别车道线检测 - python opencv

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 车位识别车道线检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) …

从六个方面对比Go和Python的差异

您是否想过 Go 与 Python 之间的主要区别是什么&#xff1f;随着对软件开发人员的需求不断增加&#xff0c;选择哪种编码语言可能会很困难。 ​ 在此&#xff0c;我们将从六个方面对比Go和Python,探讨 Go 和 Python之间的差异。我们将讨论它们的特点、优缺点&#xff0c;以便…

GPT、GPT-2、GPT-3论文精读笔记

视频&#xff1a;GPT&#xff0c;GPT-2&#xff0c;GPT-3 论文精读【论文精读】_哔哩哔哩_bilibili MAE论文&#xff1a;把bert用回计算机视觉领域 CLIP论文&#xff1a;打通文本和图像 GPT 论文&#xff1a;Improving Language Understanding by Generative Pre-Training …

史诗级云故障敲响警钟,应用保障不能没有“连续键”!

近日&#xff0c;知名云服务商出现一次史诗级的云故障&#xff1a;全球所有区域/所有服务同时异常&#xff0c;故障持续长达3小时之多&#xff0c;云上众多应用受到极大影响。 如今&#xff0c;在一个充满不确定性和复杂性的数字化时代&#xff0c;哪怕是顶级云服务商亦不能避…

并行与分布式计算 第9章 算法设计

文章目录 并行与分布式计算 第9章 算法设计9.1 设计过程9.1.1 PCAM设计过程9.1.2 划分9.1.3 通信9.1.4 组合9.1.5 映射 8.2 设计方法8.2.1 划分技术9.2.2 分治9.2.3 平衡树技术9.2.4倍增技术9.2.5 流水线技术9.2.6 破对称技术 并行与分布式计算 第9章 算法设计 9.1 设计过程 …

一张图,了解美格智能高算力AI模组

美格智能高算力A模组&#xff0c;澎湃算力让AI触手可及&#xff01;

数字化背景下,集流体行业的智能制造方法论

行业背景 随着全球对清洁能源需求的不断增加&#xff0c;新能源领域正在迅速崛起&#xff0c;在新能源技术中&#xff0c;锂电池作为一种高效、轻便的能量储存解决方案&#xff0c;正成为主流。而锂电集流体作为锂电池的核心部件&#xff0c;承担着电池内部电流分布的关键角色…

服务号可以迁移到订阅号吗

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;首先我们要看一下服务号和订阅号的主要区别。1、服务号推送的消息没有折叠&#xff0c;消息出现在聊天列表中&#xff0c;会像收到消息一样有提醒。而订阅号推送的消息是折叠的&#xff0c;“订阅号…

分布式篇---第二篇

系列文章目录 文章目录 系列文章目录前言一、你知道哪些分布式事务解决方案?二、什么是二阶段提交?三、什么是三阶段提交?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你…