【BZOJ】1054: [HAOI2008]移动玩具(bfs+hash)

时间:2023-03-08 15:51:12

http://www.lydsy.com/JudgeOnline/problem.php?id=1054

一开始我还以为要双向广搜。。。。但是很水的数据,不需要了。

直接bfs+hash判重即可。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=1000000, fx[]={-1, 1, 0, 0}, fy[]={0, 0, -1, 1};
inline const bool check(const int &x, const int &y) { if(x<0 || x>3 || y<0 || y>3) return 0; return 1; }
struct Matrix {
bool m[4][4];
int d;
}q[N], ini;
int front, tail, ans, vis[100000];
inline int hash(const Matrix &x) {
int k=1, ret=0;
rep(i, 4) rep(j, 4) { ret+=k*x.m[i][j]; k<<=1; }
return ret;
} int main() {
char c[10];
tail=1;
rep(i, 4) {
scanf("%s", c);
rep(j, 4)
q[0].m[i][j]=c[j]-'0';
}
rep(i, 4) {
scanf("%s", c);
rep(j, 4)
ini.m[i][j]=c[j]-'0';
}
int hs;
ans=hash(ini);
hs=hash(q[0]);
if(ans==hs) { printf("0"); return 0; }
vis[hs]=1;
while(front!=tail) {
Matrix &x=q[front++]; if(front==N) front=0;
rep(i, 4) rep(j, 4) if(x.m[i][j]) {
rep(k, 4) {
int px=fx[k]+i, py=fy[k]+j;
if(check(px, py) && x.m[px][py]==0) {
q[tail]=x; ++q[tail].d;
swap(q[tail].m[i][j], q[tail].m[px][py]);
hs=hash(q[tail]);
if(hs==ans) {
printf("%d", q[tail].d);
return 0;
}
if(vis[hs]) continue;
vis[hs]=1;
++tail; if(tail==N) tail=0;
}
}
}
}
return 0;
}

Description

在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移动到某人心中的目标状态。

Input

前4行表示玩具的初始状态,每行4个数字1或0,1表示方格中放置了玩具,0表示没有放置玩具。接着是一个空行。接下来4行表示玩具的目标状态,每行4个数字1或0,意义同上。

Output

一个整数,所需要的最少移动次数。

Sample Input

1111
0000
1110
0010

1010
0101
1010
0101

Sample Output

4

HINT

Source