题意:初始状态为左边空一行,然后数字在右边28个格子。末态要求按一副卡片在一行顺序排,
即第一行为11-17,第二行21-27,。。。。
可以通过四个空格来转移卡片,问从初始状态到末态最少要多少步。
思路:
1、状态太多了,需要用hash记录状态。
2、bfs
hash函数的设计:
【1】 h += (t[i][j]*base[i*8+j]); 将整个盘的状态用此值表示。它的位置就是h=hash%M;
【2】 用的是再哈希法hash =(v+10)%M来处理冲突。
总结:aim计算出来的值很大,tag常数后要加LL。
该用long long 的地方要用long long
#include<cstdio>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#define M 1000007
using namespace std;
long long tag;
long long base[33]={1};
long long hash[M];
bool flag;
struct djw
{
int bx[4],by[4];
int map[4][8];
long long step;
}w;
queue<djw> q;
int aim[4][8]=
{
11,12,13,14,15,16,17,0,
21,22,23,24,25,26,27,0,
31,32,33,34,35,36,37,0,
41,42,43,44,45,46,47,0
};
long long gethash(int t[][8])
{
long long h=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<8;j++)
{
h += t[i][j]*base[i*8+j];
}
}
if(h==tag) flag=true;
return h;
}
bool insert(long long valve)
{
long long v = valve%M;
while(hash[v]!=-1 && hash[v]!=valve)
{
v = (v+10)%M;
}
if(hash[v]==-1)
{
hash[v]=valve;
return true;
}
return false;
}
bool work(int t[][8])
{
long long fuck = gethash(t);
return insert(fuck);
}
int bfs()
{
djw cur,next;
while(!q.empty())
{
cur = q.front();
q.pop();
for(int k=0;k<4;k++)
{
next = cur;
int xx=next.bx[k];
int yy=next.by[k];
for(int i=0;i<4;i++)
{
for(int j=0;j<8;j++)
{
if(next.map[i][j]==0) continue;
if(next.map[i][j]!=next.map[xx][yy-1]+1) continue;
swap(next.map[i][j],next.map[xx][yy]);
if(work(next.map))
{
next.bx[k]=i;
next.by[k]=j;
next.step = cur.step+1;
q.push(next);
if(flag) return next.step;
}
}
}
}
}
return -1;
}
int main()
{
int T;
for(int i=1;i<33;i++)
{
base[i]=base[i-1]*2;
}
tag=98430874871LL;
scanf("%d",&T);
while(T--)
{
while(!q.empty()) q.pop();
flag=false;
int k=0;
memset(hash,-1,sizeof(hash));
w.map[0][0]=w.map[1][0]=w.map[2][0]=w.map[3][0]=0;
for(int i=0;i<4;i++)
{
for(int j=1;j<8;j++)
{
scanf("%d",&w.map[i][j]);
if(w.map[i][j]==11) {swap(w.map[i][j],w.map[0][0]);w.bx[k]=i;w.by[k++]=j;}
else if(w.map[i][j]==21) {swap(w.map[i][j],w.map[1][0]);w.bx[k]=i;w.by[k++]=j;}
else if(w.map[i][j]==31) {swap(w.map[i][j],w.map[2][0]);w.bx[k]=i;w.by[k++]=j;}
else if(w.map[i][j]==41) {swap(w.map[i][j],w.map[3][0]);w.bx[k]=i;w.by[k++]=j;}
}
}
w.step=0;
work(w.map);
q.push(w);
if(flag) printf("0\n");
else printf("%d\n",bfs());
}
return 0;
}