图论08-图的建模-状态的表达与理解 - 倒水问题为例

文章目录

  • 状态的表达
    • 例题1
    • 题解
      • 1 终止条件:有一个数位为4
      • 2 状态的改变:a表示十位数,b表示个位数
      • 3 其他设置
    • 例题2 力扣773 滑动谜题
      • Java
      • C++

状态的表达

例题1

在这里插入图片描述

从初始的(x,y)状态,到最后变成(4,?)或者(?,4).

本道题对于(x,y)的状态,可以使用10x+y进行表达,也就是变成了一个数字,分别放在不同的数位上。
但是本状态的表示方法不适用单个数组超过9的,因为一个数位只能表示0-9.。

涉及思想:状态压缩

题解

1 终止条件:有一个数位为4

if(next / 10 == 4 || next % 10 == 4) {end = next;return;
}

2 状态的改变:a表示十位数,b表示个位数

重复添加满水不影响结果

a = cur / 10, b = cur % 10;

要达到(4,?)或者(?,4)的办法

  • a桶灌满5升水
  • b桶灌满3升水
  • a桶的水倒掉
  • b桶的水倒掉
  • a桶中的水倒进b桶中 --> 最多能倒a升,还能倒b桶剩余空闲容量=(3-b桶当前容量)
  • b桶中的水倒进a桶中
nexts.add(5 * 10 + b);
nexts.add(a * 10 + 3);
nexts.add(a * 10 + 0);
nexts.add(0 * 10 + b);int x = Math.min(a, 3 - b);
nexts.add((a - x) * 10 + (b + x));int y = Math.min(b, 5 - a);
nexts.add((a + y) * 10 + (b - y));

3 其他设置

  • 访问数组用于记录访问过的状态
 boolean[] visited = new boolean[100];
  • 队列用于记录访问的每个节点的状态
Queue<Integer> queue = new LinkedList<>();
  • 记录上一个状态
pre = new int[100];
  • 记录状态变化
    • 首先要把pre数组填好,根据pre数组将遍历的过程从最终结果向前找初始状态。最终再翻转链表。
    • 做标记 设置end = -1
      如果end倒最后还是-1,说明问题没有解。
import java.util.*;
import java.util.ArrayList;public class WaterPuzzle {private int[] pre;private int end = -1;public WaterPuzzle(){Queue<Integer> queue = new LinkedList<>();boolean[] visited = new boolean[100];pre = new int[100];queue.add(0);visited[0] = true;while (!queue.isEmpty()){int cur = queue.remove();int a = cur / 10, b = cur % 10;// max a = 5, max b = 3ArrayList<Integer> nexts = new ArrayList<>();nexts.add(5 * 10 + b);nexts.add(a * 10 + 3);nexts.add(a * 10 + 0);nexts.add(0 * 10 + b);int x = Math.min(a, 3 - b);nexts.add((a - x) * 10 + (b + x));int y = Math.min(b, 5 - a);nexts.add((a + y) * 10 + (b - y));for(int next: nexts)if(!visited[next]){queue.add(next);visited[next] = true;pre[next] = cur;if(next / 10 == 4 || next % 10 == 4) {end = next;return;}}}}public Iterable<Integer> result(){ArrayList<Integer> res = new ArrayList<>();if(end == -1) return res;int cur = end;while(cur != 0){res.add(cur);cur = pre[cur];}res.add(0);Collections.reverse(res);return res;}public static void main(String[] args){System.out.println((new WaterPuzzle()).result());}
}

例题2 力扣773 滑动谜题

Java

/// Leetcode 773import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
import java.util.HashMap;public class Solution {private int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};public int slidingPuzzle(int[][] board) {Queue<String> queue = new LinkedList<>();HashMap<String, Integer> visited = new HashMap<>();String initalState = boardToString(board);if(initalState.equals("123450")) return 0;queue.add(initalState);visited.put(initalState, 0);while(!queue.isEmpty()){String cur = queue.remove();ArrayList<String> nexts = getNexts(cur);for(String next: nexts)if(!visited.containsKey(next)){queue.add(next);visited.put(next, visited.get(cur) + 1);if(next.equals("123450"))return visited.get(next);}}return -1;}private ArrayList<String> getNexts(String s){int[][] cur = stringToBoard(s);int zero;for(zero = 0; zero < 6; zero ++)if(cur[zero / 3][zero % 3] == 0)break;ArrayList<String> res = new ArrayList<>();int zx = zero / 3, zy = zero % 3;for(int d = 0; d < 4; d ++){int nextx = zx + dirs[d][0], nexty = zy + dirs[d][1];if(inArea(nextx, nexty)){swap(cur, zx, zy, nextx, nexty);res.add(boardToString(cur));swap(cur, zx, zy, nextx, nexty);}}return res;}private boolean inArea(int x, int y){return x >= 0 && x < 2 && y >= 0 && y < 3;}private void swap(int[][] board, int x1, int y1, int x2, int y2){int t = board[x1][y1];board[x1][y1] = board[x2][y2];board[x2][y2] = t;}private String boardToString(int[][] board){StringBuilder sb = new StringBuilder();for(int i = 0; i < 2; i ++)for(int j = 0; j < 3; j ++)sb.append(board[i][j]);return sb.toString();}private int[][] stringToBoard(String s){int[][] board = new int[2][3];for(int i = 0; i < 6; i ++)board[i / 3][i % 3] = s.charAt(i) - '0';return board;}public static void main(String[] args){int[][] board = {{1, 2, 3}, {4, 0, 5}};System.out.println((new Solution()).slidingPuzzle(board));}
}

C++

class Solution {
public:int slidingPuzzle(vector<vector<int>>& board) {
//记录最终状态const string sol = "123450";const int m = 2, n = 3;const int dirs[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};//记录初始状态,使用字符串记录string init;for (auto &line: board) {for (auto &grid: line) {init.push_back('0' + grid);}}//构造队列,并初始化queue<string> q{{init}};//设置unordered_set,记录访问状态unordered_set<string> vis{{init}};//记录步数int ans = 0;//开始BFSwhile (!q.empty()) {int size = q.size();for (int i = 0; i < size; ++i) {auto &p = q.front();//出口if (p == sol) {return ans;}//先找0号的位置int idx0 = p.find('0');//四联通拓展for (int a = 0; a < 4; ++a) {//求0号元素的二维新坐标int nx = idx0 / n + dirs[a][0], ny = idx0 % n + dirs[a][1];//求0号元素映射到一维数组中的坐标int idx1 = nx * n + ny;//判断边界if (nx >= 0 && nx < m && ny >= 0 && ny < n) {//交换两个元素的位置swap(p[idx0], p[idx1]);//如果当前状态没有测试过if (!vis.count(p)) {//加入访问数组vis.insert(p);//入队q.push(p);}//恢复原来的状态,继续交换位置然后将状态入队列swap(p[idx0], p[idx1]);}}q.pop();}//对头出队的时候,开始移动到下一个状态,因此步数+1++ans;}return -1;}
};

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

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

相关文章

JAVA提取嵌套夹带文件之Apache Tika

目录结构 前言tika简介Tika支持的文件格式MAVEN依赖JAVA程序JAVA测试程序测试文件测试结果部分文件提取失败参考连接 前言 Apache Tika提取文件整理如下&#xff0c;如有特定的文件需要提取可以先参照【部分文件提取失败】章节对照&#xff0c;以免浪费您的宝贵时间&#xff0c…

3.Docker的客户端指令学习与实战

1.Docker的命令 1.1 启动Docker&#xff08;systemctl start docker&#xff09; systemctl start docker1.2 查看docker的版本信息&#xff08;docker version&#xff09; docker version1.3 显示docker系统范围的信息&#xff08;docker info&#xff09; docker info1.4…

夯实c语言基础(2)

夯实c语言基础&#xff08;2&#xff09; 题干执行以下程序段执行后的输出结果分别为&#xff08;  b &#xff09;、&#xff08; a  &#xff09;、&#xff08;  a &#xff09;、&#xff08;  d &#xff09;。 程序段一&#xff1a; int i1,a0; while(i<…

亚马逊云科技:让生成式AI真正走向普惠

伴随着ChatGPT的横空出世&#xff0c;生成式AI&#xff08;Artificial Intelligence Generated Content&#xff0c;也称AIGC&#xff09;大潮也以锐不可当之势席卷全球。从各行各业的商业领袖&#xff0c;到千千万万的程序员和开发者&#xff0c;都在思考如何借助生成式AI技术…

Git https方式拉的代码IDEA推送代码报错

报错信息 fatal: could not read Username for ‘https://codehub-cn-south-1.devcloud.huaweicloud.com’: No such file or directory 18:18:39.885: [recovery_pattern] git -c credential.helper -c core.quotepathfalse -c log.showSignaturefalse push --progress --porc…

Portraiture4.0介绍与插件安装包下载

相信有很多需要经常进行图像处理的小伙伴的电脑上都有一款PS软件吧&#xff0c;PS的功能非常强大&#xff0c;各种细节处理都非常细致&#xff0c;但还是需要一些插件来帮我们快速处理图片&#xff0c;能够省去很多时间和精力。今天给大家介绍一款PS磨皮插件&#xff0c;能够快…

路由器基础(十一):ACL 配置

访问控制列表 (Access Control List,ACL) 是目前使用最多的访问控制实现技术。访问控制列表是路由器接口的指令列表&#xff0c;用来控制端口进出的数据包。ACL适用于所有的被路由协议&#xff0c;如IP、IPX、AppleTalk 等。访问控制列表可以分为基本访问控制列表和高级访问控制…

【IDEA】在工具栏设置快速创建包和类的图表

页面效果&#xff1a; 操作步骤&#xff1a; 设置 --> 外观与行为 --> 菜单与工具栏 --> 点击 主工具栏 --> 点击 ---- --> 点击 号 --> 添加操作 主菜单 --> 文件 --> 文件打开操作 --> 打开项目操作 --> 新建 --> 往下找 找到 clas…

【漏洞库】XXL-JOB 默认accessToken权限绕过导致RCE

文章目录 漏洞描述漏洞编号漏洞评级影响版本漏洞复现- EXP 编写 漏洞挖掘修复建议 漏洞描述 XXL-JOB 是一款开源的分布式任务调度平台&#xff0c;用于实现大规模任务的调度和执行。 XXL-JOB 默认配置下&#xff0c;用于调度通讯的 accessToken 不是随机生成的&#xff0c;而…

一个使用uniapp+vue3+ts+pinia+uview-plus开发小程序的基础模板

uniappuviewPlusvue3tspiniavite 开发基础模板 使用 uniapp vue3 ts pinia vite 开发基础模板&#xff0c;拿来即可使用&#xff0c;不要删除 yarn.lock 文件&#xff0c;否则会启动报错&#xff0c;这个可能和 pinia 的版本有关&#xff0c;所以不要随意修改。 拉取代码…

银行账单转换beancount

用了beancount来记账后&#xff0c;发现每月的账单手动记是一件极其麻烦的事情。 然后再github搜索一通后&#xff0c;有double-entry-generator&#xff08;https://github.com/deb-sig/double-entry-generator&#xff09;能转换支付宝/微信的账单&#xff0c;但是没有自己用…

Android工具栏ToolBar

主流APP除了底部有一排标签栏外&#xff0c;通常顶部还有一排导航栏。在Android5.0之前&#xff0c;这个顶部导航栏以ActionBar控件的形式出现&#xff0c;但AcionBar存在不灵活、难以扩展等毛病&#xff0c;所以Android5.0之后推出了ToolBar工具栏控件&#xff0c;意在取代Aci…

绝地求生msvcp140.dll丢失报错怎么办,这四个方法都可以解决

在回答这个问题之前&#xff0c;我们先来了解一下什么是msvcp140.dll。msvcp140.dll是微软Visual C 2015 Redistributable的一个组件&#xff0c;它包含了许多运行库文件&#xff0c;用于支持各种应用程序的正常运行。当你在玩《绝地求生》&#xff08;俗称“吃鸡”&#xff09…

【vscode远程开发】使用内网穿透实现在公网环境下远程访问

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…

【TypeScript】认识TypeScript

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 TypeScriptJavascript的缺点使用TypeScript重构TypeScript的编译环境全局安装TS编译环境TS编译简…

MySQL第三讲·SQL boy的CRUD操作

你好&#xff0c;我是安然无虞。 文章目录 增删查改&#xff1a;如何操作表中的数据&#xff1f;添加数据插入数据记录插入查询结果 删除数据修改数据查询数据select&#xff5c;where&#xff5c;group by&#xff5c;havingfromorder bylimit 增删查改&#xff1a;如何操作表…

Linux常用命令——chattr命令

在线Linux命令查询工具 chattr 用来改变文件属性 补充说明 chattr命令用来改变文件属性。这项指令可改变存放在ext2文件系统上的文件或目录属性&#xff0c;这些属性共有以下8种模式&#xff1a; 语法 chattr(选项)选项 a&#xff1a;让文件或目录仅供附加用途&#xff…

[Docker]四.Docker部署nodejs项目,部署Mysql,部署Redis,部署Mongodb

一.部署nodejs项目,映射端口,挂载数据卷 可以到https://hub.docker.com/去搜索node镜像,然后下载,也可以直接通过docker pull node下载镜像,然后用这个node镜像启动容器node,这样系统就集成了node服务了,在这里挂载www/node目录到容器中,并指定端口映射,运行nodejs程序,安装npm…

【Elasticsearch 未授权访问漏洞复现】

文章目录 一、漏洞描述二、漏洞复现三、修复建议 一、漏洞描述 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&am…