bzoj1054: [HAOI2008]移动玩具

时间:2024-05-21 12:03:44

hash+bfs;要注意特殊情况。(似乎连sort。lower_bound都不用数据小直接判重了。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define REP(i,s,t) for(int i=s;i<=t;i++)
struct node{
int a[5][5];int dist;
};
node A,B,q[65540];
char tmp[5];
int xx[5]={0,0,0,1,-1};
int yy[5]={0,1,-1,0,0};
bool vis[65540];
int get(node x){
int k=1,ans=0;
rep(i,4) rep(j,4) {
if(x.a[i][j]) ans+=k;
k<<=1;
}
return ans;
}
void init(){
rep(i,4){
scanf("%s",tmp);
rep(j,4) A.a[i][j]=tmp[j-1]-'0';
}
rep(i,4){
scanf("%s",tmp);
rep(j,4) B.a[i][j]=tmp[j-1]-'0';
B.dist=0;
}
}
void work(){
clr(vis,false);
int s=get(A),t=get(B);
if(s==t){
printf("0\n");return ;
}
int l=1,r=1;q[1]=B;
while(l<=r){
node x=q[l];
rep(i,4) rep(j,4) if(x.a[i][j]) rep(k,4){
int tx=i+xx[k],ty=j+yy[k];
if(!tx||!ty||tx>4||ty>4||x.a[tx][ty]) continue;
swap(x.a[i][j],x.a[tx][ty]);
x.dist++;
int temp=get(x);
if(!vis[temp]){
if(temp==s) {
printf("%d\n",x.dist);
return ;
}
vis[temp]=1;q[++r]=x;
}
swap(x.a[i][j],x.a[tx][ty]);x.dist--;
}
l++;
}
}
int main(){
init();work();return 0;
}

  

1054: [HAOI2008]移动玩具

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1764  Solved: 972
[Submit][Status][Discuss]

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

[Submit][Status][Discuss]