八数码难题
今天做了一道八数码,完全没有bfs的思路,还是请大佬点通了以下,才知道这跟bfs没有什么区别
八数码难题
之所以要把难题划掉,是因为发现这根本是一道水题,对,没错,没有你想的那么难
解题思路
首先给你的一个数,就是八数码的排列,也就是\(0\sim8\)的全排列,然后你需要搜索他怎样移动。
然后我们需要判重了,判重的方法有很多,可以用hash,但是你取模药珂学。
然后这就是hash冲突的惨案
然后就是代码了,这里判重我用的set
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
using namespace std;
set<int>s;
const int TOM = 123804765;
struct edge
{
int x,y,dis,id;
edge(){};
edge(int a,int b,int c,int d){x=a,y=b,id=c,dis=d;}
}e[100];
queue<edge>q;
int n;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int num[4][4],tx,ty;
int main(){
int fi=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++){
int a;
scanf("%1d",&a);
fi=fi*10+a;
if(a==0)tx=i,ty=j;
}
q.push(edge(tx,ty,fi,0));
s.insert(fi);
if(fi==TOM){
printf("0");
return 0;
}
while(!q.empty()){
edge u=q.front();
q.pop();
for(int i=0;i<4;i++){
int xx=dx[i]+u.x;
int yy=dy[i]+u.y;
if(xx<1||xx>3||yy<1||yy>3)continue;
memset(num,0,sizeof(num));
int k=u.id;
for(int i=3;i>=1;i--)
for(int j=3;j>=1;j--)
num[i][j]=k%10,k/=10;
num[u.x][u.y]=num[xx][yy];
num[xx][yy]=0;
k=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
k=k*10+num[i][j];
if(!s.count(k)){
s.insert(k);
q.push(edge(xx,yy,k,u.dis+1));
}
if(k==TOM){
printf("%d",u.dis+1);
return 0;
}
}
}
}