首页 > 编程语言 >845. 八数码(C++)

845. 八数码(C++)

时间:2024-03-18 15:58:17浏览次数:13  
标签:状态 845 输出 int 交换 网格 C++ 数码 str

在一个 3×3 的网格中,1∼8 这 8 个数字和一个 x 恰好不重不漏地分布在这 3×3 的网格中。

例如:

1 2 3
x 4 6
7 5 8

在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 x

例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

1 2 3   1 2 3   1 2 3   1 2 3
x 4 6   4 x 6   4 5 6   4 5 6
7 5 8   7 5 8   7 x 8   7 8 x

现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式

输入占一行,将 3×3 的初始网格描绘出来。

例如,如果初始网格如下所示:

1 2 3 
x 4 6 
7 5 8 

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个整数,表示最少交换次数。

如果不存在解决方案,则输出 −1。

输入样例:
2 3 4 1 5 x 7 6 8
输出样例
19

算法思路:

  1. 状态表示: 将每个状态表示为一个长度为 9 的字符串,其中 'x' 表示空格位置。这样的状态空间是有限的,因为总共有 9 个位置,每个位置可以是 1~8 中的一个数字或者 'x'。

  2. 广度优先搜索(BFS): 从初始状态开始,使用 BFS 算法遍历状态空间。每次将当前状态出队,然后尝试将 'x' 分别与上、下、左、右四个方向的数字交换,生成新的状态。如果新状态是首次遇到的状态,则将其加入队列,并记录当前步数。

  3. 终止条件: 当找到目标状态(正确排列)时,即 "12345678x",输出当前步数;如果队列为空仍未找到目标状态,则输出 -1。

代码:

#include <iostream>
#include <unordered_map>
#include <queue>

using namespace std;

string str;
unordered_map<string, int>h;
queue<string>q;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int main() {
    for (int i = 0; i < 9; i ++ ) {
        char c;
        cin >> c;
        str += c;
    }
    h[str] = 0;
    q.push(str);
    while (!q.empty()) {
        string s = q.front();
        q.pop();

        int pos = s.find('x'), res = h[s];
        int a = pos / 3, b = pos % 3;
        if (s == "12345678x") {
            cout << res;
            return 0;
        }
        for (int i = 0; i < 4; i ++ ) {
            int ax = a + dx[i], by = b + dy[i];
            if (ax >= 0 && ax <= 2 && by >= 0 && by <= 2) {
                swap(s[pos], s[ax *3 + by]);
                if (h.find(s) == h.end()) {
                    h[s] = res + 1;
                    q.push(s);
                }
                swap(s[pos], s[ax *3 + by]);
            }
        }
    }
    cout << "-1";
}

标签:状态,845,输出,int,交换,网格,C++,数码,str
From: https://blog.csdn.net/chq66666/article/details/136811872

相关文章

  • C++实名认证接口教程-好集成的身份证实名认证接口-三要素认证
    现如今,随着实名制的实施,各行各业都将进行人员身份的核查,如家政、保洁、物流、金融、电商等,身份证实名认证接口主要是验证个人用户提交的姓名、人像和身份证号码信息,和公安数据库内对应的数据是否匹配一致,可以验证个人身份证信息的真伪。以下是C++语言调用翔云身份证实名......
  • 【STL】 C++常用容器介绍系列(一)----(map、set、stack)
    目录一、map系列1、map介绍2、unordered_map介绍3、map和unordered_map的选择二、set系列1、set介绍2、unordered_set介绍3、set和unordered_set的选择三、如何遍历和查询map和set1、map的遍历2、map的查询3、set的遍历4、set的查询四、stack介绍和操作stack的方......
  • C++实名认证接口教程-好集成的身份证实名认证接口-三要素认证
    现如今,随着实名制的实施,各行各业都将进行人员身份的核查,如家政、保洁、物流、金融、电商等,身份证实名认证接口主要是验证个人用户提交的姓名、人像和身份证号码信息,和公安数据库内对应的数据是否匹配一致,可以验证个人身份证信息的真伪。以下是C++语言调用翔云身份证实名认......
  • 初见Cpp(C++)
        从本篇开始,往后将开始更新C++有关的文章,本篇作为对C++的一个铺垫。将会较为详细的讲解一些有关C++的基本知识,便于读者从C语言阶段晋升到C++阶段。以下是对C++的一些介绍:    C++是在C的基础上,容纳进去了面对对象的编程思想,并且增加了许多有用的库,以及编程......
  • C++考试注意事项
    选择判断题标记题干关键词(特别是否定词),避免答错方向(要求选出错误的选项,答成正确的)选择题:在得出你认为正确的答案,也要看一下其他选项,也许有更正确的答案:)对于不会的问题,可以对比不同选项之间的差异,从出题人角度思考可能得答案,以及肯定不对的答案,用排除法提升概率程序题有时......
  • C++之类和对象(3)
    目录1.再谈构造函数1.1构造函数体赋值 1.2初始化列表1.3explicit  2.static成员2.1概念 3.友元3.1友元函数3.2友元类4.内部类 5.匿名对象6.拷贝对象时编译器做出的优化1.再谈构造函数1.1构造函数体赋值classDate{public:Date(in......
  • C++ pointer
    int*pInt=newint;*pInt=5;cout<<"---------------"<<endl;cout<<"&(*pInt)-->"<<&(*pInt)<<endl;cout<<"pInt-->"<<pInt<<endl......
  • C++中的this指针、访问控制和构造函数
    C++中的this指针、访问控制和构造函数this指针在C++中,this指针是一个特殊的指针,它指向当前对象的地址。每个非静态成员函数(包括成员函数模板)都有一个this指针作为其隐含参数,这意味着在成员函数内部,this可以用来引用调用该成员函数的对象。this指针是自动传递给成员函数的,......
  • STM32 TIM3 定时器应用之数码管显示定时时间
     实现目标1、STM32基于HAL库定时器的使用;2、加强数码管的学习。一、定时器概述?1、生活中哪些场景会用到定时器?2、STM32F1定时器二、原理图设计三、STM32CubeMX配置1.定时器时钟配置2.定时器3、数码管、蜂鸣器的配置  3.开启定时器3中断四、程序......
  • C++ 面试100问--完结(十一)
    C++中虚函数是怎么实现的?        每一个含有虚函数的类都至少有有一个与之对应的虚函数表,其中存放着该类所有虚函数对应的函数指针(地址),类的示例对象不包含虚函数表,只有虚指针;派生类会生成一个兼容基类的虚函数表。C++中纯虚函数的引入有什么目的?        纯......