给一个4*8的矩阵,求移动到目标状态的最小次数。
每次操作可以将一个数换到空格处,这个数只能是 值等于空格左边+1的那个数,而且不能是*7+1.
有点像规则略有不同的拼图游戏,bfs的思路很好想,每个图有四种移动的可能(四个0的地方可以变换),记录下来,依次与目标状态比较就可以得到结果了
但重点是 状态怎么存呢。。
于是这里参考胖富帅的状态压缩思想,把这个矩阵给hash一下
但是不知道为什么是这样转换啊。。。胖富帅不理我 求解啊各位
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
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
};
int head,tail,hash;
int s[80],vis[1000007];
struct node
{
int ma[4][8];
int step;
}tmp,q[500000];
int end(int t[][8])
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<8;j++)
if(t[i][j]!=aim[i][j]) return 0;
return 1;
}
int gethash(int t[][8])
{
int i,j,k=0,hash=0;
for(i=0;i<4;i++)
for(j=0;j<8;j++)
{
s[k++]=t[i][j]/10;
s[k++]=t[i][j]%10;
//转化成数字,hash
}
for(i=0;i<k;i++)//hash
{
hash=hash*7+s[i];
}
hash=(hash&0x7fffffff)%1000007;
return hash;
}
void change(int x,int y,int v)
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<8;j++)
if(tmp.ma[i][j]==v)
{
swap(tmp.ma[x][y],tmp.ma[i][j]);
hash=gethash(tmp.ma);
if(vis[hash]==0)
{
vis[hash]=1;
tmp.step++;
q[tail++]=tmp;
tmp.step--;
}
swap(tmp.ma[x][y],tmp.ma[i][j]);//还原
return ;
}
}
int bfs()
{
int i,j,v;
memset(vis,0,sizeof vis);
head=tail=0;
q[tail++]=tmp;
hash=gethash(tmp.ma);
vis[hash]=1;
while(head!=tail)
{
tmp=q[head++];
if(end(tmp.ma)) return tmp.step;
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
if(tmp.ma[i][j]==0)
{
v=tmp.ma[i][j-1];
if(v==0||v==17||v==27||v==37||v==47) continue;
change(i,j,v+1);
}
}
}
}
return -1;
}
int main()
{
int t,i,j,v;
scanf("%d",&t);
getchar();
while(t--)
{
getchar();
for(i=0;i<4;i++)
{
tmp.ma[i][0]=(i+1)*10+1;
for(j=1;j<8;j++)
{
scanf("%d",&v);
if(v==11||v==21||v==31||v==41) tmp.ma[i][j]=0;
else tmp.ma[i][j]=v;
}
}
tmp.step=0;
printf("%d\n",bfs());
}
return 0;
}