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

news2024/11/24 8:47:33

文章目录

  • 状态的表达
    • 例题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 = 3

            ArrayList<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 773

import 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;

//开始BFS
    while (!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.coloradmin.cn/o/1162921.html

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

相关文章

7.OsgEarth加载Obj模型

愿你出走半生,归来仍是少年&#xff01; 除了大面积的倾斜摄影的加载&#xff0c;同时还存在单个模型的加载。常用的obj模型作为单体在三维场景中的呈现。 原理类似于6.OsgEarth加载倾斜摄影-CSDN博客中的倾斜加载。 1.代码 通过osg读取文件作为节点添加到GeoTransform节点中&…

hadoop mapreduce的api调用WordCount本机和集群代码

本机运行代码 package com.example.hadoop.api.mr;import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache…

破局:如何从产业角度锻造企业不败竞争优势?

引言&#xff1a;究竟是坚守过去的辉煌,还是勇敢拥抱未来的变化?柯达的沉沦与富士胶片的崛起,揭示企业如何通过深刻理解自身的核心竞争力&#xff0c;利用产业战略的转变来实现持续发展。从产品竞争到产业升级,这不仅仅是一场商业竞赛的变革&#xff0c;更是一次企业战略思维的…

数据结构与算法—“二叉树”的实现

目录 一、二叉树链式结构的实现 1、声明结构体 2、创建新节点 3、创建二叉树 二、二叉树的遍历 1、前序遍历讲解 2、节点个数 3、叶子节点个数 4、二叉树的高度 5、第k层节点个数 6、查找值为x的节点 完整版代码&#xff1a; 一、二叉树链式结构的实现 1、声明结构体 我们为二…

【每日一练 | 华为认证真题练习Day11】

华为真题从Day1 开始的真题可留言获取 ​ Day11 华为认证中级考试真题 1、下面哪些是对网络进行管理的主要目标?(多选) A.确保网络用户收到期望的网络服务质量与技术服务信息 B.减少设备的搬迁费用 C.减少网络设备使用年限&#xff0c;和延长服务周期 D.帮助网络工程师…

nebula-br local-store 模式,快速搭建主备集群实践

因为线上图数据库目前为单集群&#xff0c;数据量比较大&#xff0c;有以下缺点&#xff1a; 单点风险&#xff0c;一旦集群崩溃或者因为某些查询拖垮整个集群&#xff0c;就会导致所有图操作受影响很多优化类但会影响读写的操作不好执行&#xff0c;比如&#xff1a;compact、…

HANA:计算视图-图形化视图-“参数“-引用表数据(性能优化)

1.前言 最近项目HANA部分的开发用的比较多&#xff0c;之前很少用图形化计算视图&#xff0c;最近研究了下&#xff0c;发现有些小功能对于图形化视图的性能提升&#xff0c;还有建模便利性都有很大帮助&#xff0c;今天发现了一个小功能&#xff0c;就是视图中的参数&#xf…

两种办法实现进制转换:将十进制数N转换成为r进制数

两种办法实现进制转换&#xff1a;将十进制数N转换成为r进制数 法一&#xff1a;递归 //进制转换 void change1(int N,int r) {if (N / r 0) {printf("%d", N%r);}else {change1(N/r, r);printf("%d", N%r);} }int main() {int N 0;int r 0;printf(&q…

grid布局中grid-row和grid-column

目录 一、grid-row 二、grid-column 三、实例 一、grid-row grid-row属性定义了网格元素行的开始和结束位置。结合了grid-row-start和grid-row-end grid-row: 1 / 3;//表示行线从第一行线到第三行线为止 二、grid-column grid-column属性定义了网格元素列的开始和结束位置…

企业税收违法查询API:提升财务监控和风险管理的关键利器

引言 随着企业税务环境的不断演变和政府对税收合规性的日益关注&#xff0c;企业面临着更多的税务合规挑战。为了降低税务风险&#xff0c;提高财务监控水平&#xff0c;许多企业已经开始采用先进的工具和技术。其中之一&#xff0c;便是企业税收违法查询API&#xff0c;这一强…

大神总结:做数据可视化,谨记三要、两不要

直观灵活分析数据&#xff0c;让数据更易懂的数据可视化报表是由大量不同类型的数据可视化图表组成的&#xff0c;那数据可视化图表又是怎么制作出来的&#xff1f;在制作数据可视化报表的过程中需要注意哪些事项&#xff1f; BI数据可视化工具里预设大量的数据可视图表&#…

魔术般的速度,焕然一新的磁盘空间 - Magic Disk Cleaner for Mac 2023

在当今这个信息时代&#xff0c;我们的磁盘空间无时无刻不在被各种文件和数据所填满。无论是工作文件&#xff0c;还是日常生活的照片、视频&#xff0c;亦或是下载的各种应用程序&#xff0c;都在不断地蚕食着我们的磁盘空间。面对这种情况&#xff0c;一款高效、便捷的磁盘垃…

竞赛选题 深度学习实现行人重识别 - python opencv yolo Reid

文章目录 0 前言1 课题背景2 效果展示3 行人检测4 行人重识别5 其他工具6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的行人重识别算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c…

用友U8+ CRM任意文件上传漏洞

用友U8 CRM任意文件上传漏洞 免责声明漏洞描述漏洞影响漏洞危害网络测绘Fofa: body"用友U8CRM" 漏洞复现1. 构造poc2. 复现3. 访问webshell 免责声明 仅用于技术交流,目的是向相关安全人员展示漏洞利用方式,以便更好地提高网络安全意识和技术水平。 任何人不得利用该…

I/O性能优化——这一篇就足够啦

背景 继上一篇CPU性能优化文章 &#xff0c;本次向大家分享关于I/O性能优化的分析套路以及常见措施。后续还有关于内存及网络优化的篇章。 基本概念 对于I/O我们先了解几个概念&#xff0c;文件系统&#xff0c;磁盘&#xff0c;文件。 磁盘 磁盘为系统提供了最基本的持久化存…

香港高端人才通行证计划入围高校/全球百强大学综合名单公布!

香港高端人才通行证计划入围高校/全球百强大学综合名单公布&#xff01; 香港高才通计划希望吸引世界各地具备丰富工作经验及高学历的人才到香港探索机遇&#xff0c;这些高端人才包括高收入人士和在世界顶尖大学毕业的学生。 此计划并不适用于阿富汗、古巴、老挝、朝鲜、尼泊尔…

低功耗WiFi模块的技术发展

随着物联网的迅速发展&#xff0c;对于低功耗设备和技术的需求日益增加。低功耗WiFi模块应运而生&#xff0c;为连接大量设备提供了更长的电池寿命和更可持续的能源解决方案。本文将深入研究低功耗WiFi模块的技术发展&#xff0c;探讨其在物联网和移动设备领域的关键作用。 1.…

LEEDCODE 2235两整数相加

class Solution { public:int sum(int num1, int num2) {return (num1 num2);} };

AD9361 数据数字接口说明

一、简要 AD9361和BBP之间的数据接口以两种模式之一工作&#xff1a;标准CMOS兼容模式或低压差分信号&#xff08;LVDS&#xff09;兼容模式。本篇文章将简要介绍一下CMOS和LVDS工作模式下的数据具体的传输样式。 二、CMOS 工作模式 P0_D[11:0] and P1_D[11:0]: 端口0&#xf…

Firefox修改缓存目录的方法

打开Firefox&#xff0c;在地址栏输入“about:config” 查找是否有 browser.cache.disk.parent_directory&#xff0c;如果没有就新建一个同名的字符串&#xff0c;然后修改值为你要存放Firefox浏览器缓存的目录地址&#xff08;E:\FirefoxCacheFiles&#xff09; 然后重新…