AcWing 845. 八数码

在这里插入图片描述

在这里插入图片描述
这道题如同难度一样,确实不好上手,既然求最短路径,直接bfs就好,但是bfs的核心就是标记,我们该怎么标记一个字符串呢,我们发现这个字符串很特殊,我们标记的只有这个字符串的全排列,然后我也是学到了一个康托的一个算法,然后我就去看了一下,在长长的代码下,还是AC了,最难的点就是怎么把字符串哈希,可能蓝桥杯好像可以用map,map的时间效率明显很低。
不多说
代码如下。

#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int N=362880;

bool book[N];
struct point
{
    int x;
    int y;
    int foot;
    char p[10];
};


int fact[10];
char mod[10],k[10];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};



int hash_cal(char s[])//对字符串哈希的一个算法,最难的点
{
    int cnt=0,ans=0;
    for(int i=0;i<9;i++)
    {   
    cnt=0;
    for(int j=0;j<i;j++)
    {
        if(s[j]>s[i])
        cnt++;
    }
    ans+=cnt*fact[i];
    }
    return ans;
}

int bfs(int st)
{
    queue<point> q;
    point k,z;
    k.x=st/3;
    k.y=st%3;
    k.foot=0;
    strcpy(k.p,mod);
    q.push(k);
    while(q.size())
    {
        k=q.front();
        q.pop();
        int sx=k.x,sy=k.y;
        for(int i=0;i<4;i++)
        {
            int tx=sx+dx[i];
            int ty=sy+dy[i];
            if(0<=tx&&0<=ty&&tx<=2&&ty<=2)
            {
                char rev[10];
                strcpy(rev,k.p);
                rev[k.x*3+k.y]=rev[tx*3+ty];
                rev[tx*3+ty]='x';
                if(!strcmp(rev,"12345678x"))
                return k.foot+1;
                if(!book[hash_cal(rev)])
                {
                    book[hash_cal(rev)]=true;
                    z.x=tx;
                    z.y=ty;
                    strcpy(z.p,rev);
                    z.foot=k.foot+1;
                    q.push(z);
                }
            }
        }
    }
    return -1;
    
    
    
}
int main(void)
{
    fact[0]=1;
    for(int i=1;i<9;i++) fact[i]=i*fact[i-1];
    char op[2];
    int st;
    for(int i=0;i<9;i++)
    {
        scanf("%s",op);
        if(op[0]=='x') st=i;
        mod[i]=op[0];
    }
    mod[9]=0;
    cout<<bfs(st)<<endl;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值