还是隐士图搜索的题目,代码就是ljr书上的,基本还是一个bfs,不同的是这里的判重不能用一个vis25维的数组来简单判断了,哈希函数的方法,还有第二种是set<int> vis;用了一个容器,感觉这个比较好用。
#include<cstdio>
#include<cstring>
#include<cstdlib>
//#include<set>
using namespace std;
typedef int state[26];
#define MAXSTATE 5000000
state st[MAXSTATE],goal= {1,1,1,1,1,-1,1,1,1,1,-1,-1,0,1,1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1};
int dist[MAXSTATE];
const int dx[]= {2,2,-2,-2,1,1,-1,-1};
const int dy[]= {1,-1,1,-1,2,-2,2,-2};
const int MAXHASHSIZE=10000003;
int head[MAXHASHSIZE],next[MAXHASHSIZE];
void init_lookup_table()
{
memset(head,0,sizeof(head));
}
int hash(state &s)
{
int v=0;
for(int i=0; i<25; i++)
v=v*2+s[i];
return v%MAXHASHSIZE;
}
int try_to_insert(int s)
{
int h=hash(st[s]);
int u=head[h];
while(u)
{
if(memcmp(st[u],st[s],sizeof(st[s]))==0) return 0;
u=next[u];
}
next[s]=head[h];
head[h]=s;
return 1;
}
/*set<int> vis;
void init_lookup_table()
{
vis.clear();
}
int try_to_insert(int s)
{
int v=0;
for(int i=0;i<25;i++)
v=v*10+st[s][i];
if(vis.count(v)) return 0;
vis.insert(v);
return 1;
}*/
int bfs()
{
init_lookup_table();
int front=1,rear=2;
while(front<rear)
{
state &s=st[front];
if(dist[front]>10) return -1;
if(memcmp(goal,s,sizeof(s))==0) return front;
int z;
for(z=0; z<25; z++)
if(!s[z]) break;
int x=z/5,y=z%5;
for(int d=0; d<8; d++)
{
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*5+newy;
if(newx>=0&&newx<5&&newy>=0&&newy<5)
{
state &t=st[rear];
memcpy(&t,&s,sizeof(s));
t[newz]=s[z];
t[z]=s[newz];
dist[rear]=dist[front]+1;
if(try_to_insert(rear)) rear++;
}
}
front++;
}
return 0;
}
int main()
{
//freopen("in.txt","r",stdin);
int cas;
scanf("%d",&cas);
getchar();
while(cas--)
{
int p=0;
char c;
for(int i=0; i<5; i++)
{
for(int j=0; j<5; j++)
{
scanf("%c",&c);
if(c=='0') st[1][p++]=-1;
else if(c=='1') st[1][p++]=1;
else if(c==' ') st[1][p++]=0;
}
getchar();
}
int ans=bfs();
if(ans>0&&dist[ans]<11)
printf("Solvable in %d move(s).\n",dist[ans]);
else printf("Unsolvable in less than 11 move(s).\n");
}
return 0;
}