题目
八段码,没错,题目就个这,啊哈哈,看得我一脸懵,咱也不知道啥是个八段码,幸好有万能的度娘姐姐~
八段码,这个题是做什么的呢?其实就是:给你两个3*3的矩阵,里面填的数分别是0-8,通过移动0的位置,使矩阵A达到矩阵B的状态
思路
坦白地讲,我看到的时候是没思路的,搜了几篇博客,没找到我想要的方法,我就努力的找啊找,最终还是被我找到了,一个宝藏博主,简洁明了,反正我看懂了,不过他没什么解析,所以,我来了
先附上原文链接
这道题呢,我没什么心路历程,毕竟我也是看的别人的代码
所以直接讲解题方法
1、用什么来存储这两个矩阵呢?
这个问题其实很关键,我搜到的博客里,大多都是用字符串来存储的,至于为什么,我没想大概是因为我们要判断两个状态是否一致,如果用数组的话,要挨个字符去判断,太费时间,字符串会省时省力一些
2、用字符串怎么实现0的移动呢?
确切地说,这用字符串就不好实现了,数组明显方便一点的啦,用下标操作,所以,到现在为止,我们才可以确定我们的存储形式:字符串+数组,当然,字符串是主导,数组只是为了转移方便而引入
3、判断过程是什么呢?怎么实现呢?
其实这就是本题的核心,在这里,我们要对每移动一次的状态进行判断,同时每次移动都有(0-4)种方案,这样说的话,会不会很熟悉,其实一涉及到这样的问题,用队列都是一种好办法,或者说这个过程是变相的广度优先搜索,所以等价一下就是广度优先要用队列
代码
干讲也太没意思了,所以放到代码里看,要看注释喔!
#include <bits/stdc++.h>
/*
八段码
*/
using namespace std;
int main()
{
int x_change[4]={0,1,0,-1};
int y_change[4]={1,0,-1,0};
//这两个数组是为了转移而设置的,分别对应上下左右
string a,b,temp;
//a是原始串,b是目标串
a=b="";
for(int i=0;i<9;i++)
{
cin>>temp;
a+=temp;
}
for(int i=0;i<9;i++)
{
cin>>temp;
b+=temp;
}
map<string,int> m;
//m用来记录步数,即从到当前string走了多少步
m[a]=0;
//cout<<a<<" "<<b<<endl;
queue<string> q;
q.push(a);
while(!q.empty())
{
temp=q.front();
q.pop();
if(temp==b)//循环结束的条件:找到目标串状态
{
cout<<m[temp]<<endl;//返回当前所走步数
break;
}
int dis=m[temp];//记录当前步数
int index=temp.find('0');//找出0的位置
for(int i=0;i<4;i++)//将0的位置转换为数组表示
{
int x,y;
x=index/3+x_change[i];
y=index%3+y_change[i];
if(x<0||x>2||y<0||y>2)//数组越界
continue;
swap(temp[index],temp[x*3+y]);//状态转移,即交换0和与它相邻的某个数字
if(m.count(temp)==0)//如果这个状态不在队列里,如果已存在,则无需重复入队
{
m[temp]=dis+1;//记录当前所走步数
q.push(temp);//将其入队,等待走下一步
}
swap(temp[index],temp[x*3+y]);//这里很重要!!!在当前状态下,每次都要回退,因为他们是并行的,而不是串联的
}
}
return 0;
}