http://acm.hdu.edu.cn/showproblem.php?pid=1067
题意:每次将比空白格前面一个数字大一的数字移动到空白格,如果空白格前面数字的个位数是 7 或者空白格前面是空白格则不能移动到这里。
思路:手写hash,BFS。
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int mod = 1000007;
struct node{
int step;
int zero[4][2];
int loca[4][8];
int mapn[4][8];
friend bool operator == (node a, node b){
for(int i = 0; i < 4; i++){
for(int k = 1; k < 8; k ++)
{
if(a.mapn[i][k] != b.mapn[i][k])
return false;
}
}
return true;
}
};
node endmap;
long long Hash[mod];
void Swap(node &w, int i, int sx, int sy, int tx, int ty)
{
w.mapn[sx][sy] = w.mapn[tx][ty];
w.mapn[tx][ty] = 0;
w.zero[i][0] = tx;
w.zero[i][1] = ty;
w.loca[w.mapn[sx][sy]/10-1][w.mapn[sx][sy]%10-1] = sx * 10 + sy;
}
bool HashMap(node w)
{
long long resl = 0;
for(int i = 0; i < 4; i++){
for(int k = 0; k < 8; k++)
{
resl = (resl << 1) + (long long)w.mapn[i][k];
}
}
int hs = resl % mod;
while(Hash[hs] != resl && Hash[hs]){
hs = (hs + 5) % mod;
}
if(Hash[hs] == 0){
Hash[hs] = resl;
return false;
}
return true;
}
int Bfs(node w)
{
queue<node>que;
que.push(w);
HashMap(w);
while(!que.empty()){
node r = que.front();
que.pop();
if(r == endmap)
return r.step;
for(int i = 0; i < 4; i++){
int mid = r.mapn[r.zero[i][0]][r.zero[i][1]-1];
if(mid % 10 == 7 || mid % 10 == 0)
continue;
w = r;
w.step++;
mid = mid + 1;
int loc = w.loca[mid/10-1][mid%10-1];
Swap(w, i, r.zero[i][0], r.zero[i][1], loc/10, loc%10);
if(!HashMap(w)){
que.push(w);
}
}
}
return -1;
}
int main()
{
int Test;
cin>>Test;
for(int i = 0; i < 4; i++){
for(int k = 0; k < 7; k++)
{
endmap.mapn[i][k] = 10 * (i + 1) + k + 1;
}
endmap.mapn[i][7] = 0;
}
while(Test--)
{
node w;
memset(Hash, 0, sizeof(Hash));
for(int i = 0; i < 4; i++){
for(int k = 1; k < 8; k++)
{
cin>>w.mapn[i][k];
if(w.mapn[i][k] % 10 == 1){
w.zero[w.mapn[i][k]/10-1][0] = i;
w.zero[w.mapn[i][k]/10-1][1] = k;
w.mapn[w.mapn[i][k]/10-1][0] = w.mapn[i][k];
w.mapn[i][k] = 0;
}
else{
w.loca[w.mapn[i][k]/10-1][w.mapn[i][k]%10-1] = i*10 + k;
}
}
}
w.step = 0;
cout<<Bfs(w)<<endl;
}
return 0;
}