动态规划求二维网格中从左上角到右下角的最短路径( 每次只能向下、向右、向右下走 ) 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.hqwc.cn/news/211309.html

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

相关文章

时间序列分析算法的概念、模型检验及应用

时间序列分析是一种用于研究随时间变化的数据模式和趋势的统计方法。这类数据通常按照时间顺序排列&#xff0c;例如股票价格、气温、销售额等。时间序列分析的目标是从过去的观测中提取信息&#xff0c;以便预测未来的趋势。 以下是关于时间序列分析的一些重要概念、模型检验…

蓝桥杯算法双周赛心得——迷宫逃脱(dp)

大家好&#xff0c;我是晴天学长&#xff0c;dp版的来啦&#xff0c;可以是受益匪浅啊&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1) .迷宫逃脱 迷官逃脱[算法赛] 问题描述 在数学王国中&#xff0c;存…

【办公常识_1】写好的代码如何上传?使用svn commit

首先找到对应的目录 找到文件之后点击SVN Commit

STM32——外部中断

文章目录 0.中断关系映射1.使能 IO 口时钟&#xff0c;初始化 IO 口为输入2.设置 IO 口模式&#xff0c;触发条件&#xff0c;开启 SYSCFG 时钟&#xff0c;设置 IO 口与中断线的映射关系。3.配置NVIC优先级管理&#xff0c;并使能中断4.编写中断服务函数。5.编写中断处理回调函…

浅析智慧社区建设趋势及AI大数据监管平台方案设计

一、背景与需求 伴随着社会与经济的发展&#xff0c;人们对生活质量的要求越来越高&#xff0c;与此同时&#xff0c;新兴技术的进步也促进了智慧社区市场的逐步成熟。智慧社区是社区管理的一种新理念&#xff0c;是新形势下城市与社会管理的一种创新模式。 在上海、杭州、深…

ELK架构

经典的ELK 经典的ELK主要是由Filebeat Logstash Elasticsearch Kibana组成&#xff0c;如下图&#xff1a;&#xff08;早期的ELK只有Logstash Elasticsearch Kibana&#xff09; 此架构主要适用于数据量小的开发环境&#xff0c;存在数据丢失的危险。 整合消息队列Ngin…

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

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

催单开发信怎么写?外贸人如何写催单邮件?

年末催单开发信编写技巧&#xff1f;最有效的催单话术有哪些&#xff1f; 催单开发信成为了企业间日常沟通的重要一环。这些信件不仅有助于促进业务发展&#xff0c;还可加强供应链的协调&#xff0c;确保货物及时送达。蜂邮EDM将介绍如何写一封出色的催单开发信&#xff0c;以…

WorkPlus解放企业应用开发,实现跨平台无缝切换

在移动应用的快速发展时代&#xff0c;企业对于自主开发和应用平台替换的需求日益增长。WorkPlus作为一个完整的移动数字化APP底座&#xff0c;为企业提供了独立自主的应用开发环境&#xff0c;实现了平台无关性和应用解耦。今天&#xff0c;我们将深入探讨WorkPlus在企业应用开…

【攻防世界-misc】pure_color

1.方法一&#xff1a;用画图工具打开图片&#xff0c;将图片拷贝至虚拟机win7桌面&#xff0c; 点“属性”&#xff0c;颜色设置为“黑白”&#xff0c; 出现flag值。 2.方法二&#xff1a;使用Stegsilve打开&#xff0c;分析图片 将图片打开&#xff0c;按左右键查找&#xff…

SVD 最小二乘法解 亲测ok!

线性最小二乘问题 m个方程求解n个未知数&#xff0c;有三种情况&#xff1a; mn且A为非奇异&#xff0c;则有唯一解&#xff0c;xA.inverse()*bm>n&#xff0c;约束的个数大于未知数的个数&#xff0c;称为超定问题&#xff08;overdetermined&#xff09;m<n&#xff0…

【开发实践】使用AES算法加密 .sql文件

一、需求分析 笔者在开发遇到一个小需求&#xff0c;导出数据的sql文件&#xff0c;由于安全监管的需要&#xff0c;对sql文件进行加密处理。实现将sql文件进行加密&#xff0c;最终呈现如下效果&#xff1a; 二、加密文件 1、加密模块 /*** AES加密算法** param sourceFileP…