题意:
求从给出的状态到达目标状态需要多少步,无法到达或大于20输出No solution!
解题思路:
哈希+双向搜索,好长呦。
代码:
<pre name="code" class="cpp">#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
const int INF=1e9+7;
const double eps=1e-7;
const int mod=1000007;
const int maxn=5000000;
int f[2],r[2];
int dx[]={-1,0,1,0},dy[]={0,-1,0,1};
int qq;
bool in(int x,int y){ return x>=0&&x<5&&y>=0&&y<5; }
struct node
{
int px[2],py[2];
int A[5][5];
}nod[2][maxn];
int B[5][5]={
-1,-1,0,-1,-1,
-1,1,2,3,-1,
4,5,6,7,8,
-1,9,10,11,-1,
-1,-1,0,-1,-1
};
bool Same(int A[][5])
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
if(A[i][j]!=B[i][j]) return false;
return true;
}
int F[20]; //??2^i
void GetF()
{
F[0]=1;
for(int i=1;i<15;i++) F[i]=F[i-1]*2;
}
int Get(int A[][5])
{
int ret=0,k=0;
for(int i=0;i<5;i++)
for(int j=0;j<5;j++) if(A[i][j]>0) ret+=F[k++]*A[i][j];
return ret;
}
struct Hash
{
int v,next,nid,k;
}ha[mod+maxn];
int hash_id;
bool check(int a,int k1,int b,int k2)
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
if(nod[k1][a].A[i][j]!=nod[k2][b].A[i][j]) return false;
return true;
}
int Insert_Hash(int v,int nid,int k)
{
int a=v%mod;
int p=ha[a].next;
while(p!=-1)
{
if(check(ha[p].nid , ha[p].k , nid , k))
return ha[p].k;
p=ha[p].next;
}
p=++hash_id;
ha[p].v=v; ha[p].nid=nid; ha[p].k=k;
ha[p].next=ha[a].next; ha[a].next=p;
return -1;
}
bool AddNode(node t,int i,int j,int k)
{
int x=t.px[i],y=t.py[i];
int nx=x+dx[j],ny=y+dy[j];
if(!in(nx,ny)||t.A[nx][ny]<=0) return false;
node& tt=nod[k][r[k]];
tt=t;
swap(tt.A[x][y],tt.A[nx][ny]);
tt.px[i]=nx; tt.py[i]=ny;
int a=Insert_Hash(Get(tt.A),r[k],k);
if(a==-1){ r[k]++; return false; }
else if(a==k) return false;
else return true;
}
void Print(node& t)
{
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++) printf("%d ",t.A[i][j]);
puts("");
}
puts("=========");
getchar();
}
bool bfs(int k)
{
int& be=f[k];
int en=r[k];
while(be<en)
{
node t=nod[k][be++];
for(int i=0;i<2;i++)
for(int j=0;j<4;j++) if(AddNode(t,i,j,k)) return true;
}
return false;
}
int solve()
{
if(Same(nod[0][0].A)) return 0;
for(int i=0;i<5;i++)
for(int j=0;j<5;j++) nod[1][0].A[i][j]=B[i][j];
nod[1][0].px[0]=0; nod[1][0].py[0]=2;
nod[1][0].px[1]=4; nod[1][0].py[1]=2;
int step=0;
f[0]=f[1]=0,r[0]=r[1]=1;
for(int i=0;i<mod;i++) ha[i].next=-1;
hash_id=mod;
while(f[0]<r[0]||f[1]<r[1])
{
step++;
if(bfs(0)) return step;
step++;
if(bfs(1)) return step;
if(step>=20)
{
// cout<<step<<endl;
return -1;
}
}
return -1;
}
int main()
{
int T;
GetF();
scanf("%d",&T);
while(T--)
{
qq=20;
int k=0;
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
{
if(B[i][j]==-1) { nod[0][0].A[i][j]=-1; continue; }
scanf("%d",&nod[0][0].A[i][j]);
if(nod[0][0].A[i][j]==0)
{ nod[0][0].px[k]=i; nod[0][0].py[k++]=j; }
}
int ans=solve();
if(ans==-1) printf("No solution!\n");
else printf("%d\n",ans);
}
return 0;
}