算法提高 八数码

原题链接 is here

题目
八段码,没错,题目就个这,啊哈哈,看得我一脸懵,咱也不知道啥是个八段码,幸好有万能的度娘姐姐~
八段码,这个题是做什么的呢?其实就是:给你两个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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值