洛谷P1379八数码难题
题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。
要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765)。
找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入输出格式
输入格式:
输入初始状态,一行九个数字,空格用0表示
输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
输入输出样例
输入:
283104765
输出:
4
分析:
八数码难题,对于我这个C++蒟蒻来说还真有点难,在经过dalao的指点后终于AC了这道题.
先将思路,题面很短相信大家都能看懂,虽然我的代码较长但是应该是最好理解的吧,由题目得知我们有9个数,
其中有一个数字0剩下的数字都能和0交换位置即在数字0能和它的上下左右交换位置(在不超出边界的情况下),
然后我们需要知道当一个矩阵最后交换到"123804765"这种情况的最小步数,最小又是矩阵从这一点我们可以判断出,
此题很有可能用BFS来写,那么问题又来了我们怎么标记?转换成矩阵标记?不不不那样就太麻烦了而且代码也不好实现,
再看题"123804765"其实这已经提示我们可以用字符串来标记,那么怎么标记,我们可以用map<string,bool> vis来实现这个标记功能,
用map就能存下字符型的数组了所以我们每次仅需要判断vis[XX]是否走过就可以完成标记了.
接下来将搜索的实现.
标记我们知道怎么实现,那么关于这道题的搜索又怎么实现?
我们可以由题目得知每个数字只能和0进行交换,我们就可以想到我们可以用0进行对矩阵中每个数字进行更新我们可以用swap实现,
对两个数字进行交换,因为能进行数字交换只能是单个字符的操作所以我们就又得将这些字符全部压进一个新的字符串里这里使用
字符串.push_back(字符)即可实现,然后将新的字符串进行判断是否和"123804765"相同如果相同我们就输出当前的步数,由BFS的最优性
如果满足当前的情况的那就是最优解,注意这里一定要想清楚因为我们每次交换一次每次都更新整个字符串所以当字符串重复时这个情况是不满足的
所我们还要将字符swap回去,当然因为每次交换都会使Map的值发生改变,所以我们也必须swap回去,知道了这些这道题写起来就比较容易了.
在搜索开始前我们当然要进行对这个字符串的预处理当然这个要实现很简单我在这里就不不解释了
更详细的理解请看代码
代码:
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <map>
using namespace std;
int startx,starty,posx=,posy=;//我这个变量名这么清楚可能没人不懂对吧
string s;
char Map[][];
int dirx[]={,,,-};//因为只有四个方向
int diry[]={,,-,};
map<string,bool> vis;//这里我们用map来进行判断重复
struct Node //结构体来存数
{
int x,y,t;
string s;//这里我们声明s来进行判断和更新
};
void bfs()
{
vis[s]=true;//起点肯定要赋值为true啊
queue<struct Node> que;
struct Node now;
now.x=startx;now.y=starty;now.t=;now.s=s;
que.push(now);
while(!que.empty())
{
now=que.front();
que.pop();
posx=,posy=;
for(int i=;i<s.length();i++)//其实这里写在下面比较好理解但不影响
{
Map[posx][posy]=now.s[i];//这里的操作就是我们将我们每次更新完的字符串再用MAP重新赋值再就进行搜索
posy++;
if(posy==)//如果这一排满了
{
posy=;//换下一排
posx++;
}
}
if(now.s=="")//如果满足情况
{
cout<<now.t<<endl;//输出因为BFS最优的特点我们就可以直接输出
return;
}
for(int i=;i<;i++)
{
int xx=dirx[i]+now.x;
int yy=diry[i]+now.y;
if(xx<||xx>||yy<||yy>) continue;//边界处理
swap(Map[now.x][now.y],Map[xx][yy]);
string change;//这里我们需要重新声明一个字符串来进行判断和更新操作
for(int i=;i<=;i++)//因为3*3的矩阵
{
for(int j=;j<=;j++)
change.push_back(Map[i][j]);//将字符全部压进字符串里
}
if(vis[change])//这里需要注意这里很重要当它为重复的情况我们还要swap回去才能continue
{//因为如果我们当前这个不满足情况的值会改变会对后面的搜索产生干扰所以必须swap回去才能continue
swap(Map[xx][yy],Map[now.x][now.y]);
continue;
}
vis[change]=true;
swap(Map[xx][yy],Map[now.x][now.y]);//这里和上面那个是差不多的意思这里因为我们这个BFS和以往的不同因为我们直接是将答案进行了跟新,所以如果我们不更新为上一个状态那会对下一个循环产生影响这个地方难理解需要好好想一下
struct Node next;
next.x=xx;next.y=yy;next.s=change;next.t=now.t+;//这里BFS的基本操作
que.push(next);
}
}
return;
}
int main()
{
cin>>s;
for(int i=;i<s.length();i++)//预处理
{
Map[posx][posy]=s[i];
if(Map[posx][posy]=='')//0为起点
{
startx=posx;//找到它的坐标
starty=posy;
}
posy++;
if(posy==)//当这排y为4时这排就满了因为我是从1开始的所以要到4
{
posy=;//posy赋值为1
posx++;//进入到下一排
}
}
bfs();
return ;
}
洛谷P1379八数码难题的更多相关文章
- 洛谷 P1379 八数码难题 解题报告
P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...
- 洛谷——P1379 八数码难题
P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...
- 洛谷 P1379 八数码难题 Label:判重&&bfs
特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...
- 洛谷 P1379 八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...
- 洛谷 - P1379 - 八数码难题 - bfs
https://www.luogu.org/problemnew/show/P1379 #include <bits/stdc++.h> using namespace std; #def ...
- 洛谷—— P1379 八数码难题
https://daniu.luogu.org/problem/show?pid=1379 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示 ...
- 洛谷P1379 八数码难题
传送门 1.先用dfs枚举9!的全排列,存到hash数组里(类似离散化),因为顺序枚举,就不需要排序了 2.朴素bfs,判重就用二分找hash:如果发现当前状态=要求状态,输出步数结束程序 上代码 # ...
- 洛谷 P1379 八数码难题 题解
我个人感觉就是一道bfs的变形,还是对bfs掌握不好的人有一定难度. 本题思路: 大体上用bfs搜,用map来去重,在这里只需要一个队列,因为需要较少步数达到的状态一定在步数较多的状态之前入队列. # ...
- 洛谷 P1379 八数码难题(map && 双向bfs)
题目传送门 解题思路: 一道bfs,本题最难的一点就是如何储存已经被访问过的状态,如果直接开一个bool数组,空间肯定会炸,所以我们要用另一个数据结构存,STL大法好,用map来存,直接AC. AC代 ...
随机推荐
- 【luogu P2299 Mzc和体委的争夺战】 题解
题目链接:https://www.luogu.org/problemnew/show/P2299#sub 裸的迪杰斯特拉(我是在考试前复习一下板子) #include<iostream> ...
- 9.异常Exception
9.1 异常概述 package exception; /* * 异常:程序运行的不正常情况 * * Throwable: 异常的超类 * |-Error * 严重问题,这种问题我们通过异常处理是不能 ...
- SpringBoot学习17:springboot热部署配置
spring为开发者提供了一个名为spring-boot-devtools的模块来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot应用. devtool ...
- Webpack学习笔记九 webpack优化总结
webpack 优化笔记 webpack4 自带的优化包括 swingTree(摇摆树)和作用域提升 swingTree 比如入口文件 index.js引入通用方法 util, 里面有 10个方法, ...
- DB2 SQL Error: SQLCODE = -798, SQLSTATE = 428C9
DB2 SQL Error: SQLCODE = -798, SQLSTATE = 428C9报错是因为 , 你往设置了ALWAYS自增的列里面插了初始值 . ALWAYS自增设置如下. -- 设置主 ...
- oracle12c管理作业资源的一种方式
数据库:12.1.0.2,rac,cdb模式 笔者负责移动两个12.1.0.2的cdb集群,一个在aix上,一个在linux上,不幸的是,它们都是混合型,数据有100多T. 由于其它部门交付的时候,已 ...
- 汇编:采用址表的方法编写程序实现C程序的switch功能
//待实现的C程序 1 void main() { ; -) { : printf("excellence"); break; : printf("good") ...
- Generating Complex Procedural Terrains Using GPU
前言:感慨于居然不用tesselation也可以产生这么复杂的地形,当然致命的那个关于不能有洞的缺陷还是没有办法,但是这个赶脚生成的已经足够好了,再加上其它模型估 计效果还是比较震撼的.总之好文共分享 ...
- ethereum Pet Shop
在部署宠物商店时遇到的一些坑,给大家总结一下,以免大家多走弯路 转载的地址(详细):https://steemit.com/cn/@lucia3/ethereum-pet-shop 启动"n ...
- QQ群技术:0成本创建2000人QQ群技巧
群人数,直接关系群权重;于排名,意义非凡;此法靠谱,笔者亲测. 就说这张图,这类关键词,要是没2000人群,不管你多流弊,你是做不上去滴. 于QQ群霸屏,笔者有太多的笔墨,各种排名技巧,阿力推推早前明 ...