【刷题】搜索——BFS:八数码【A*模板】

news2025/1/8 18:55:50

A*简介

某点u的距离f(u)定义如下:
f ( u ) = g ( u ) + h ( u ) f(u) = g(u) + h(u) f(u)=g(u)+h(u)
g(u):起点到u走的距离
h(u):u到终点估计的距离,保证 0 ≤ h ( u ) ≤ h ′ ( u ) 0 \leq h(u) \leq h'(u) 0h(u)h(u)。其中h’(u)是真实距离

和普通BFS不同,A*算法用的是优先队列,根据f从小到大排序(小根堆)。拓展点时只有g(u)变小才进队,终点出队时停止。

性质1

估计距离<=真实距离,保证了终点第一次出队时,一定是最优解。

反证法:
假设终点e第一次出队时距离f(e)不是最优解f(e)',之后才会由其他点更新进队再出队得到最优解。
由于之后还要再更新,所以最优解路径上总有点会在队列里,不妨设点为u。
那么 g ( u ) + h ( u ) ≤ g ( u ) + h ′ ( u ) = f ( e ) ′ g(u) + h(u) \leq g(u) + h'(u) = f(e)' g(u)+h(u)g(u)+h(u)=f(e)
因为D不是最优解,所以 f ( e ) > f ( e ) ′ f(e) > f(e)' f(e)>f(e),故有 f ( e ) > f ( e ) ′ ≥ g ( u ) + h ( u ) = f ( u ) f(e) > f(e)' \geq g(u) + h(u) = f(u) f(e)>f(e)g(u)+h(u)=f(u)
那么此时应该出队的是点u,而不是终点,矛盾。

性质2

除了终点以外的点出队,不一定是最优解
假设点u是最优解上的点,起点到u有两条路径a和b,真实距离分别是3和5。假设所有点的h都为0,但是路径a上某点v的h(v)为一个很大的数(但小于到终点的真实距离)。

那么在进队时,走到点v前,会先将路径b上的其他点都进队(因为h(v)很大导致f(v)很大)。并通过路径b更新u的距离5,此时u的最优距离显然是3。

基于这个性质,A*无法判断重复,只能通过终点出队停止。
PS. BFS入队时就可以判断重复,dijkstra出队的时候判断重复。

八数码

题目

在这里插入图片描述题目链接
x表示空位置,每次可以将一个数字移到空位置上,问从给定状态移动到目标状态(1 2 3 4 5 6 7 8 x)至少要几步。
输入初始状态,输出x移动的路径,上下左右对应:u、d、l、r。无解输出unsolvable。

判断是否有解

可以看序列的逆序对的数量,偶数则有解,奇数则无解

必要性:如果有解则逆序对数量是基数。

如题目所示:
2 3 4
1 5 x
7 6 8
序列为:2 3 4 1 5 x 7 6 8

当移动的数是左右移动时,例如5向右移,不会改变序列的位置,逆序对不变。
当移动的数是上下移动时,例如8向上移。序列变为:2 3 4 1 5 8 7 6 x。可以看到上下移只会导致一个数往前后往后移动两位。那么只有可能改变两个逆序对,这边是新增(8, 7),(8, 6),其他情况则是减少两个、或者加一减一。都不会改变逆序对的奇偶性。

充分性证明较复杂,不再赘述。

估计距离函数h

当前状态中各个数的位置,到其目标位置的曼哈顿距离之和。

代码

#include <iostream>
#include <queue>
#include <vector>
#include <unordered_map>
using namespace std;

typedef pair<int, string> PIS;

void findX(int &x, int &y, string &ts) {
    for (int i = 0; i < 9; i ++ ) {
        if (ts[i] == 'x') {
            x = i / 3;
            y = i % 3;
        }
    }
}

int h(string s) {
    int dis = 0;
    for (int i = 0; i < 9; i ++ ) {
        if (s[i] == 'x') continue;
        int num = s[i] - '1';
        dis += abs(num / 3 - i / 3) + abs(num % 3 - i % 3);
    }
    return dis;
}

string bfs(string start) {
    priority_queue<PIS, vector<PIS>, greater<PIS>> heap;
    unordered_map<string, int> g;
    unordered_map<string, PIS> pre;
    string ans;
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, -1, 0, 1};
    char ds[5] = "uldr";

    heap.push({h(start), start});
    g[start] = 0;
    while(!heap.empty()) {
        PIS t = heap.top();
        heap.pop();
        string ts = t.second;
        if (ts == "12345678x") {
            while(ts != start) {
                PIS preTs = pre[ts];
                int i = preTs.first;
                ts = preTs.second;
                ans = ds[i] + ans;
            }
            return ans;
        }

        int x, y;
        findX(x, y, ts);

        for (int i = 0; i < 4; i ++ ) {
            int tx = x + dx[i];
            int ty = y + dy[i];
            if (tx > 2 || ty > 2 || tx < 0 || ty < 0) continue;
            string newS = ts;
            swap(newS[x * 3 + y], newS[tx * 3 + ty]);
            if (!g.count(newS) || g[newS] > g[ts] + 1) {
                g[newS] = g[ts] + 1;
                heap.push({g[newS] + h(newS), newS});
                pre[newS] = {i, ts};
            }
        }
    }
    return "";
}

int main() {
    char ch;
    string input, invS;
    for (int i = 0; i < 9; i ++ ) {
        cin >> ch;
        input += ch;
        if (ch != 'x')  invS += ch;
    }
    int invCnt = 0;
    for (int i = 0; i < 9; i ++ ) {
        for (int j = i + 1; j < 9; j ++ ) {
            if (invS[i] > invS[j]) {
                invCnt ++ ;
            }
        }
    }
    if (invCnt & 1) {
        printf("unsolvable\n");
    }
    else {
        string ans = bfs(input);
        cout << ans << endl;
    }
    
    return 0;
}

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

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

相关文章

健康体检信息系统源码,个人体检、团队体检、体检报告、统计分析

健康体检管理系统源码 PEIS源码 数据对接 体检人员管理系统&#xff0c;系统有演示&#xff0c;文档齐全。 一套专业的体检管理系统源码&#xff0c;该系统涵盖个人体检、团队体检、关爱体检等多种体检类型&#xff0c;提供体检登记管理、体检结果管理、体检报告打印及发放…

阿里云服务器搭建网站流程by宝塔Linux面板

阿里云服务器安装宝塔面板教程&#xff0c;云服务器吧以阿里云Linux系统云服务器安装宝塔Linux面板为例&#xff0c;先配置云服务器安全组开放宝塔所需端口8888、888、80、443、20和21端口&#xff0c;然后执行安装宝塔面板命令脚本&#xff0c;最后登录宝塔后台安装LNMP&#…

尝试图像锐化

#图像锐化 拉普拉斯&#xff1a; 导数f(x,y)f(x1,y)f(x−1,y)f(x,y1)f(x,y−1)−4f(x,y) 可以扩展到8邻域&#xff1a; ​ Mat Sharpen(Mat input, int percent, int type) { Mat result; Mat s input.clone(); Mat kernel; switch (type) { case 0: kernel (Mat_(3, 3)…

4个令人惊艳的ChatGPT项目,开源了

自从 ChatGPT、Stable Diffusion 发布以来&#xff0c;各种相关开源项目百花齐放&#xff0c;着实让人应接不暇。今天&#xff0c;将着重挑选几个优质的开源项目&#xff0c;对我们的日常工作、学习生活&#xff0c;都会有很大的帮助。 一、Visual ChatGPT 这个是微软开源的项…

代码随想录_二叉树_leetcode700、98

leetcode700.二叉搜索树中的搜索 700. 二叉搜索树中的搜索 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 示例 1: 输入&…

乘客出租出行需求短时预测

CLAB模型是一种空间-时间环境下基于深度学习的乘客流量预测模型&#xff0c;可有效挖掘出租车乘客出行的时空相关性&#xff0c;考虑历史数据流入量对出行需求的影响&#xff0c;从而提高预测准确性。 数据挖掘维度&#xff1a; 1.时间维度&#xff1a;预测的是短时预测&#x…

关于ONgDB我问了ChatGPT这些问题!

关于ONgDB我问了ChatGPT这些问题&#xff01; 关于ONgDB我问了ChatGPT这些问题&#xff01;提问 ChatGPTONgDB和Neo4j的区别是什么&#xff1f;ONgDB可以适配哪些版本的Neo4j软件包&#xff1f;ONgDB可以适配哪个版本的Neo4j Python驱动软件包&#xff1f;ONgDB 1.x版本的特点是…

Oracle系列之八:SQL查询

SQL查询 1. 基本查询2. 连接查询3. SQL语句解析4. Oracle Hint Oracle它提供了一个强大的SQL引擎&#xff0c;使得用户可以通过SQL语言来管理和操作数据库。 1. 基本查询 以CAP&#xff08;顾客-代理-产品&#xff09;数据库为例&#xff0c;表结构如下&#xff1a; CUSTOME…

第四章 单例模式

文章目录 前言一、单例模式的介绍二、单例模式的 8 种实现方式&#xff08;懒汉式要注意线程安全问题&#xff09;1、饿汉式&#xff08;静态常量&#xff09;优缺点&#xff1a;可能会造成内存的浪费&#xff0c;但也只能浪费内存 2、饿汉式&#xff08;静态代码块&#xff09…

( “树” 之 BST) 538. 把二叉搜索树转换为累加树 ——【Leetcode每日一题】

二叉查找树&#xff08;BST&#xff09;&#xff1a;根节点大于等于左子树所有节点&#xff0c;小于等于右子树所有节点。 二叉查找树中序遍历有序。 538. 把二叉搜索树转换为累加树 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加…

( “树” 之 DFS) 337. 打家劫舍 III ——【Leetcode每日一题】

337. 打家劫舍 III 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为 root。 除了 root 之外&#xff0c;每栋房子有且只有一个“父“房子与之相连。一番侦察之后&#xff0c;聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。…

IDEA社区版搭建Tomcat服务器并创建web项目

IDEA社区版搭建Tomcat服务器并创建web项目 目标 创建Web项目的目录结构可以启动Tomcat服务器编写Servlet并访问成功 问题 IDEA社区版没有创建Web工程的选项IDEA社区版没有Tomcat插件 实现步骤 针对以上两个问题&#xff0c;分步解决 问题一&#xff1a;IDEA社区版没有创建…

《花雕学AI》18:AI绘画尝鲜Prompt Hunt,使用人工智能模型来创造、探索和分享艺术作品

引言&#xff1a; 人工智能是当今科技领域的热门话题&#xff0c;它不仅可以帮助人类解决各种实际问题&#xff0c;也可以激发人类的创造力和艺术感。Prompt Hunt就是一个利用人工智能模型来创造、探索和分享艺术作品的AI绘画网站。它提供了三种不同的模型&#xff0c;分别是S…

Git 分布式版本控制工具

文章目录 Git 分布式版本控制工具课程内容1. 前言1.1 什么是Git1.2 使用Git能做什么 2. Git概述2.1 Git简介2.2 Git下载与安装 TODO3. Git代码托管服务3.1 常用的Git代码托管服务3.2 码云代码托管服务3.2.1 注册码云账号3.2.2 登录码云3.2.3 创建远程仓库3.2.4 邀请其他用户成为…

最火爆的持续集成工具 jenkins ,详细教程来啦(傻瓜式教程)

很多小伙伴在安装以及配置jenkins的时候&#xff0c;总会遇到一些问题。 今天在这边特地把jenkins的安装&#xff0c;以及常用的一些功能的配置整理到了这篇文章中&#xff0c;希望对大家有所帮助&#xff01; 1安装JDK JDK安装完需要配置环境变量&#xff0c;大家可以自行百度…

Spark学习:spark读写postgreSql

读写PostgreSql 一、环境搭建二、写三、读四、ETL一、环境搭建 1、spark安装包,官网地址,我下的是如下版本 2、postgreSql数据库jdbc驱动,官网地址,我下的是如下版本 3、java版本1.8;scala版本2.12.15 4、spark安装包解压到任意目录,把postgreSql的jdbc驱动jar包放在spark的…

MySQL having关键字详解、与where的区别

1、having关键字概览 1.1、作用 对查询的数据进行筛选 1.2、having关键字产生的原因 使用where对查询的数据进行筛选时&#xff0c;where子句中无法使用聚合函数&#xff0c;所以引出having关键字 1.3、having使用语法 having单独使用&#xff08;不与group by一起使用&a…

L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事 有趣的数据结构题

传送门:PTA 题目描述: 给定一棵 n 个节点的树&#xff0c;其中节点 r 为根。求该树所有可能的 DFS 序中逆序对数量之和。 输入: 10 5 10 2 2 5 10 7 7 1 7 9 4 2 3 10 10 8 3 6 输出: 516唉,由于近期事情比较多以及某些个人因素导致好久没有更新博客了,今天碰到了一道有意思的…

机器视觉检测技术在工业零部件的应用

众所周知&#xff0c;在工业生产中&#xff0c;传统的检测技术需要大量的检测工作者&#xff0c;不仅影响生产效率&#xff0c;而且带来不可靠的因素。 视觉检测技术克服了传统检测技术的缺点&#xff0c;确保了检测的安全性。 可靠性和自动化程度高&#xff0c;已成为当前检测…

Scrapy配置使用

前人之述备矣 教程&#xff1a;Python虚拟环境ScrapyPyCharm 使用实例 - 知乎 注意&#xff1a;是cmd不是powershell,两者还是有区别的。 因为是本地的虚拟环境&#xff0c;用cmd激活环境并且安装相关的scrapy包&#xff0c;如果用powershell&#xff0c;在pycharm中显示不了…