这道题和hdu1043 Eight问题可以认为是同一类问题,
针对这道题,是手动实现的hash, 而Eight问题是利用康托展开式 ,康托数和排列一一对应本质还是hash
这两道是典型的状态搜索题,
这里纪念下
下面是ac代码,思路源于其他网友,这里借鉴
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
struct Node{
int g[4][8];
int step;
bool operator ==(const Node& other)const{
for(int i=0;i<4;i++){
for(int j=0;j<8;j++)
if(g[i][j]!=other.g[i][j])return false;
}
return true;
}
long long Hash(){
long long code=0;
for(int i=0;i<4;i++){
for(int j=0;j<8;j++){
code+=(long long)(code<<(long long)1)+ (long long) (g[i][j]);
}
}
return code;
}
};
const int maxn=100007;
long long Hash[maxn];
Node Start,End;
queue<Node> q;
void Insert(long long value){
int v=value%maxn;
while(Hash[v]!=-1&&Hash[v]!=value){
v+=31; // hash again
v%=maxn;
}
if(Hash[v]==-1){
Hash[v]=value;
}
}
bool isInsert(long long value){
int v=value%maxn;
while(Hash[v]!=-1&&Hash[v]!=value){
v+=31;
v%=maxn;
}
if(Hash[v]==-1) return false;
return true;
}
void initStart(){
for(int i=0;i<4;i++){
Start.g[i][0]=0;
for(int j=1;j<8;j++){
scanf("%d",&Start.g[i][j]);
}
}
}
void initEnd(){
for(int i=0;i<4;i++){
for(int j=0;j<7;j++){
End.g[i][j]=(i+1)*10+j+1;
}
End.g[i][7]=0;
}
}
void bfs(){
Node first,next;
q.push(Start);
while(!q.empty()){
first=q.front();
q.pop();
for(int i=0;i<4;i++){
for(int j=0;j<8;j++){
//find the blank
if(!first.g[i][j]){
next=first;
next.step++;
//find the val
int val=first.g[i][j-1]+1;
int fx,fy;
bool flag=false;
// base the rule no node can move 7 or blank right
if(val==1||val%10==8) continue;
for(int p=0;p<4;p++){
for(int k=0;k<8;k++){
if(first.g[p][k]==val){
fx =p,fy=k;
flag=true;
}
}
}
// find the value that can move the blank
if(flag){
int tmp=next.g[i][j];
next.g[i][j]=first.g[fx][fy];
next.g[fx][fy]=tmp;
if(next==End){
printf("%d\n",next.step);
return ;
}
long long value=next.Hash();
if(!isInsert(value)){
Insert(value);
q.push(next);
}
}
}
}
}
}
printf("-1\n");
}
void soluation(){
// first move 11,21,31,41 to the first place;
int i,j;
int r=0;
int tmp=4;
//search 11,21,31,41
while(tmp--)
for( i=0;i<4;i++){
for(j=1;j<8;j++){
if(Start.g[i][j]==(r+1)*10+1){
Start.g[r++][0]=Start.g[i][j];
Start.g[i][j]=0;
}
}
}
if(Start==End){
printf("0\n");
return ;
}
bfs();
}
int main()
{
int n;
cin>>n;
int t=n;
initEnd();
while(t--){
memset(Hash,-1,sizeof(Hash));
initStart();
while(!q.empty()) q.pop();
soluation();
}
return 0;
}