当前位置: 首页 > article >正文

洛谷题目: P1225 黑白棋游戏 题解 (本题难)

题目传送门:

P1225 黑白棋游戏 - 洛谷 (luogu.com.cn)

前言:

这道题要求我们找出从黑白棋游戏的初始棋盘状态变化到目标棋盘状态的最短着棋序列,也就是要找到最少的交换相邻方格棋子的步数以及每一步具体的交换位置。我们可以使用广度优先搜索(BFS)算法来解决这个问题,难度不大,以下是作者整理的本题整体思路:

题目整体思路(总结):

        广度优先搜索是一种适合用于寻找最短路径的算法,因为它会逐层扩展节点,一旦找到目标节点,所经过的路径必然是最短的。在本题中,每个棋盘状态可以看作图中的一个节点,相邻状态之间存在一条边。我们从初始状态开始,逐层扩展可能的状态,直到找到目标状态。

#具体实现步骤:

        1、状态表示:

                为了方便存储和比较棋盘状态,我们需要将二维的棋盘状态转换为一维的字符串。例如,对于一个 4x4 的棋盘,我们可以将其按行展开成一个长度为 16 的字符串,其中每个字符代表一个方格的棋子颜色。

        2、数据结构设计:

                Steate结构体:  

                        用于存储当前的棋盘状态以及到达该状态所经过的移动序列。移动序列用

 vector<pair<pair<int, int>, pair<int, int>>>   表示,其中每个   pair<pair<int, int>, pair<int, int>>   代表依次交换操作,包含着两个相邻方格的坐标。

                队列 que<State>:

                        用于广搜,存储待扩展的状态。

                哈希集合  unordered_set<string>  :

                        用于记录已经访问过的状态,避免重复搜索。

        3、相邻方格判断:

                编写一个函数 isadjacent 来判断两个方格是否相邻。在二维平面中,两个方格相邻以为着它们的曼哈顿距离为1,即横坐标差的绝对值加上纵坐标差的绝对值等于1.

        4、棋子交换操作:

                编写一个函数  swapieces  来实现交换两个相邻方格棋子的操作。该函数接受当前期盼状态和两个方格的坐标作为参数返回交换后的新棋盘状态。

##广度优先搜索过程:

        1、初始化:

                将初始状态加入队列,并将标记为已访问。

        2、扩展状态:

                从队列中取出一个状态,对于该状态下的每一个方格,检查其相邻方格。如果相邻方格合法,则交换这两个方格的棋子,得到一个新的状态。

        3、判断新状态:

                将新状态转换为字符串,如果该字符串不在已访问集合中,则将新状态加入队列,并更新移动序列和已访问集合。

        4、终止条件:

                当取出的状态与目标状态相同时,搜索结束,返回对应的移动序列。

        5、输出结果:

                输出移动序列的长度(即着棋步数),并依次输出每一步的交换信息,格式为 abcd,表示将棋盘上 (a, b) 处的棋子与 (c, d) 处的棋子换位。

###复杂度分析:

        1、时间复杂度:

                由于棋盘共有 16 个方格,每个方格有 2 种可能的颜色(白或黑),所以总的状态数为  2^{16}  。在最坏情况下,我们需要遍历所有可能的状态,因此时间复杂度为  O(2^{16})  .

        2、空间复杂度:

                主要用于存储队列和已访问状态集合,空间复杂度同样为  O(2^{16})  

####代码:

#include <bits/stdc++.h>
using namespace std;struct S {string board;vector<pair<pair<int, int>, pair<int, int>>> moves;
};
string bs(const vector<vector<int>>& board) {string r;for (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {r += to_string(board[i][j]);}}return r;
}
bool A(int x1, int y1, int x2, int y2) {return (abs(x1 - x2) + abs(y1 - y2) == 1);
}
vector<vector<int>> spieces(const vector<vector<int>>& board, int x1, int y1, int x2, int y2) {vector<vector<int>> nb = board;swap(nb[x1][y1], nb[x2][y2]);return nb;
}
vector<pair<pair<int, int>, pair<int, int>>> bfs(const vector<vector<int>>& start, const vector<vector<int>>& target) {string targetStr = bs(target);queue<S> q;unordered_set<string> v;S initial;initial.board = bs(start);q.push(initial);v.insert(initial.board);while (!q.empty()) {S current = q.front();q.pop();if (current.board == targetStr) {return current.moves;}vector<vector<int>> cb(4, vector<int>(4));for (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {cb[i][j] = current.board[i * 4 + j] - '0';}}for (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {for (int dx = -1; dx <= 1; ++dx) {for (int dy = -1; dy <= 1; ++dy) {if ((dx == 0 && dy == 0) || (abs(dx) + abs(dy) != 1)) continue;int ni = i + dx;int nj = j + dy;if (ni >= 0 && ni < 4 && nj >= 0 && nj < 4) {vector<vector<int>> nb = spieces(cb, i, j, ni, nj);string ns = bs(nb);if (v.find(ns) == v.end()) {S next;next.board = ns;next.moves = current.moves;next.moves.emplace_back(make_pair(i + 1, j + 1), make_pair(ni + 1, nj + 1));q.push(next);v.insert(ns);}}}}}}}return {};
}int main()
{vector<vector<int>> start(4, vector<int>(4));vector<vector<int>> target(4, vector<int>(4));for (int i = 0; i < 4; ++i) {string line;cin >> line;for (int j = 0; j < 4; ++j) {start[i][j] = line[j] - '0';}}for (int i = 0; i < 4; ++i) {string line;cin >> line;for (int j = 0; j < 4; ++j) {target[i][j] = line[j] - '0';}}vector<pair<pair<int, int>, pair<int, int>>> moves = bfs(start, target);cout << moves.size() << endl;for (const auto& move : moves) {cout << move.first.first << move.first.second << move.second.first << move.second.second << endl;}return 0;
}

相关文章:

洛谷题目: P1225 黑白棋游戏 题解 (本题难)

题目传送门&#xff1a; P1225 黑白棋游戏 - 洛谷 (luogu.com.cn) 前言&#xff1a; 这道题要求我们找出从黑白棋游戏的初始棋盘状态变化到目标棋盘状态的最短着棋序列&#xff0c;也就是要找到最少的交换相邻方格棋子的步数以及每一步具体的交换位置。我们可以使用广度优先…...

网络安全技术分析:攻防演进、核心技术与未来挑战

本文系统梳理网络安全技术发展脉络&#xff0c;聚焦漏洞利用、威胁检测、数据保护三大核心领域&#xff0c;结合APT攻击、勒索软件、零日漏洞等典型案例&#xff0c;解析防火墙、IDS、零信任架构等技术原理。通过分析2023年全球重大安全事件&#xff08;如MOVEit漏洞攻击、Lock…...

SpringBoot与Redisson整合,用注解方式解决分布式锁的使用问题

文章引用&#xff1a;https://mp.weixin.qq.com/s/XgdKE2rBKL0-nFk2NJPuyg 一、单个服务 1.代码 该接口的作用是累加一个值&#xff0c;访问一次该值加1 RestController public class LockController {Autowiredprivate StringRedisTemplate stringRedisTemplate;GetMappin…...

通过Typora + PicGo + 阿里云对象存储(OSS)实现图床

文章目录 通过Typora PicGo 阿里云对象存储&#xff08;OSS&#xff09;实现图床1 准备工作1.1 阿里云对象存储 OSS配置创建oss存储空间bucket获取AccessKey 1.2 PicGo配置1.3 Typora配置 2 使用流程3 常见问题和解决3.1 创建asesskey3.2 You have no right to access this o…...

爱普生FC-12M石英晶体谐振器精准时钟源解决方案

在当今数字化时代&#xff0c;电子设备无处不在&#xff0c;从我们日常使用的智能手机、平板电脑&#xff0c;到复杂的工业控制系统、通信基站&#xff0c;每一台设备的稳定运行都离不开精准的时钟信号。而在众多提供时钟信号的元件中&#xff0c;爱普生 FC-12M 石英晶体谐振器…...

【css酷炫效果】纯CSS实现手风琴折叠效果

【css酷炫效果】纯CSS实现手风琴折叠效果 缘创作背景html结构css样式完整代码效果图 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;https://download.csdn.net/download/u011561335/90492015 缘 创作随缘&#xff0c;不定时更新。 创作背景 刚看到csdn出活动了&am…...

AI辅助的逆向分析

AI大模型结合反编译工具与AI的辅助分析能力&#xff0c;已能实现部分代码逻辑的还原与重构。 1. 技术实现路径 &#xff08;1&#xff09;二进制文件预处理与反编译 反编译工具&#xff1a;需先使用IDA Pro、Ghidra等工具将二进制文件转换为低级中间表示&#xff08;如汇编代…...

物理标签与逻辑标签的区别

物理标签和逻辑标签都可以被机器&#xff08;如浏览器、爬虫、屏幕阅读器&#xff09;解析和识别&#xff0c;但它们的 语义信息 对机器的意义不同。以下是详细解释&#xff1a; 1. 物理标签的解析 可以识别&#xff1a;浏览器会正确解析物理标签&#xff08;如 <b>、<…...

脚本语言 Lua

概念 Lua由标准C编写而成&#xff0c;几乎在所有操作系统和平台上都可以编译、运行。Lua脚本可以很容易地被C/C 代码调用&#xff0c;也可以反过来调用C/C的函数&#xff0c;这使得Lua在应用程序中可以被广泛应用。Lua并没有提供强大的库&#xff0c;它是不适合作为开发独立应…...

《Linux 网络架构:基于 TCP 协议的多人聊天系统搭建详解》

一、系统概述 本系统是一个基于 TCP 协议的多人聊天系统&#xff0c;由一个服务器和多个客户端组成。客户端可以连接到服务器&#xff0c;向服务器发送消息&#xff0c;服务器接收到消息后将其转发给其他客户端&#xff0c;实现多人之间的实时聊天。系统使用 C 语言编写&#x…...

目前主要虚拟世界平台在单一实例承载人数和伺服器架构的综合比较分析(从开资料和技术推估):

目前主要虚拟世界平台在单一实例承载人数和伺服器架构的综合比较分析&#xff08;从开资料和技术推估&#xff09;&#xff1a; 1. 《Fortnite》&#xff08;Epic Games&#xff09; 一般游戏模式约 100人/场&#xff0c;但大型活动&#xff08;如演唱会&#xff09;采用分层串…...

鸿蒙NEXT项目实战-百得知识库04

代码仓地址&#xff0c;大家记得点个star IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点&#xff1a; 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三…...

函数的介绍

1.函数的概念 在C语言中也有函数的概念&#xff0c;有些翻译为&#xff1a;子程序&#xff0c;这种翻译更为准确。C语言的函数就是一个完成某项特定的任务的一小段代码。这段代码是有特殊的写法和调用方法的。 C语言的程序其实是有无数个小的函数组合而成的&#xff0c;也可以…...

源自Deformable Convolutional Networks的一种可变形卷积实现解析

衍生记录&#xff1a;深度学习pytorch之简单方法自定义9类卷积即插即用 文章目录 概述1. 可变形卷积的背景2. DeformConv2D概述2.1 构造函数分析2.2 前向传播函数解析2.2.1 偏移量的计算与应用2.2.2 目标位置的计算2.2.3 四个角的插值2.2.4 双线性插值的权重2.2.5 特征图的采样…...

记一次性能调优-20250320

2月份年后上班&#xff0c;刚过完年&#xff0c;还没从喜悦中解放出来&#xff0c;凌晨3点的时候同事就给我打电话&#xff0c;晚上的批量处理任务卡住了&#xff0c;快帮忙看看&#xff0c;做了几分钟的心里建设之后从被窝爬起来&#xff0c;看着手机上好几电话&#xff0c;赶…...

Postman高级功能深度解析:Mock Server与自动化监控——构建高效API测试与监控体系

引言&#xff1a;Postman在API开发中的核心价值 在数字化时代&#xff0c;API&#xff08;应用程序编程接口&#xff09;已成为系统间交互的“神经网络”&#xff0c;其质量直接影响用户体验与业务连续性。然而&#xff0c;传统API测试面临两大挑战&#xff1a; 开发阶段依赖…...

【最后203篇系列】020 rocksdb agent

今天还是挺开心的一天&#xff0c;又在工具箱里加了一个工具。嗯&#xff0c;但是快下班的时候也碰到一些不太顺心的事&#xff0c;让我有点恼火。我还真没想到一个专职的前端&#xff0c;加测试&#xff0c;以及其他一堆人&#xff0c;竟然不知道后端返回的markdown,在前端渲染…...

OpenCV旋转估计(2)用于自动检测波浪校正类型的函数autoDetectWaveCorrectKind()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::detail::autoDetectWaveCorrectKind 是 OpenCV 中用于自动检测波浪校正类型的函数&#xff0c;它根据输入的旋转矩阵集合来决定使用哪种波浪…...

mysql-connector-python 报错(0xC0000005)

报错情况&#xff1a; 原因&#xff1a; mysql-connector-python版本不对&#xff0c;我们的mysql版本为sql8.0需要下载mysql-connector-python8.0....的库 方法&#xff1a; pip install mysql-connector-python8.1.0 即可...

从零开始实现Stable Diffusion本地部署

1. 依赖安装 文件打包下载地址&#xff08;Stable Diffusion&#xff09; # git &#xff1a; 用于下载源码 https://git-scm.com/downloads/win # Python 作为基础编译环境 https://www.python.org/downloads/ # Nvidia 驱动&#xff0c;用于编译使用GPU显卡硬件 https://ww…...

RAG各类方法python源码解读与实践:利用Jupyter对RAG技术综合评测【3万字长文】

检索增强生成&#xff08;RAG &#xff09;是一种结合信息检索与生成模型的混合方法。它通过引入外部知识来提升语言模型的性能&#xff0c;从而提高回答的准确性和事实正确性。为了简单易学&#xff0c;不使用LangChain框架或FAISS向量数据库&#xff0c;而是利用Jupyter Note…...

transform C++标准库算法用法(对容器中元素进行转换操作:大小写转换、向量的加法乘法运算)

std::transform 是 C 标准库中的一个算法&#xff0c;用于对容器&#xff08;如数组、向量、字符串等&#xff09;中的元素进行转换操作&#xff0c;并将结果存储到指定的目标位置。它可以对单个范围或两个范围的元素进行操作&#xff0c;并将结果写入另一个容器。 1. 头文件 …...

Java File 类与文件操作

一、引言 在 Java 编程中,文件操作是一项非常常见且重要的任务。无论是读取配置文件、保存用户数据,还是进行日志记录,都离不开对文件的操作。Java 提供了 File 类来表示文件和目录的抽象路径名,通过该类可以对文件和目录进行创建、删除、重命名等操作。同时,Java 还提供…...

Python 字符串的编码格式

在 Python 中,字符串(str)默认使用 Unicode 编码,具体来说,Python 3 中的字符串是以 UTF-8 编码存储的 Unicode 字符序列。Unicode 是一种国际标准,旨在为世界上所有的字符提供唯一的编码,而 UTF-8 是 Unicode 的一种实现方式,具有兼容性和高效性。 1. Unicode 与 UTF-…...

RPA+AI 技术到底好在哪里?

在自动化领域&#xff0c;RPA与生成式AI都是强大的技术&#xff0c;都可以用来实现自动执行重复耗时的任务。 主要区别是&#xff1a;传统RPA擅长处理结构化与规则明确简单的流程&#xff0c;而在非结构化数据处理、动态上下文适应、智能决策等能力上有欠缺&#xff1b;而基于…...

flowable适配达梦7 (2.1)

经过第一版的问题解决&#xff0c;后端项目可以启动&#xff0c;前端页面也集成进去。 前端在流程设计页面报错 之后发现主要是组件中modelerStore这个值没有 解决方法:在data增加对象 给component/process/designer.vue 中涉及到的每个子组件传入 :modelerStore“modeler…...

基于java的ssm+JSP+MYSQL的母婴用品网站(含LW+PPT+源码+系统演示视频+安装说明)

系统功能 管理员功能模块&#xff1a; 主页 个人中心 用户管理 商品分类管理 商品信息管理 留言板管理 成长交流 系统管理 订单管理 留言管理 用户功能模块&#xff1a; 主页 个人中心 我的收藏管理 订单管理 前台首页功能模块&#xff1a; 首页 商品信息 论…...

面试八股 —— Redis篇

重点&#xff1a;缓存 和 分布式锁 缓存&#xff08;穿透&#xff0c;击穿&#xff0c;雪崩&#xff09; 降级可作为系统的保底策略&#xff0c;适用于穿透&#xff0c;击穿&#xff0c;雪崩 1.缓存穿透 2.缓存击穿 3.缓存雪崩 缓存——双写一致性 1.强一致性业务&#xff08…...

gradle-8.13

gradle-8.13 稍微看了下&#xff0c;基于Maven改造的 https://gradle.org/install/https://github.com/gradle/gradle-distributions/releaseshttps://github.com/gradle/gradle-distributions/releases/download/v8.13.0/gradle-8.13-all.zip https://github.com/gradle/gra…...

不使用负压电源,ADC如何测量正负压?

电路图来自ZLinear的开源数据采集板卡DL8884_RFN&#xff0c;是一个比较常见的电压偏置采集法 对电路进行分析&#xff0c;所以说可以先看下采集卡的模拟输入部分的参数如下&#xff1a; 通道数量: 8通道单端输入/4通道差分输入 分辨率: 16位逐次逼近型(SAR) ADC 采样速率: 40…...