3856 - 移动玩具

通过次数

0

提交次数

0

时间限制 : 1 秒 内存限制 : 128 MB

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

题目输入

前4行表示玩具的初始状态,每行4个数字1或0,1表示方格中放置了玩具,0表示没有放置玩具。

接着是一个空行。

接下来4行表示玩具的目标状态,每行4个数字1或0,意义同上。

题目输出

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

输入/输出样例

输入格式

1111
0000
1110
0010
1010
0101
1010
0101

输出格式

4

C++解答

#define MAXN 80010UL
#define MAXS 5UL

#include <cstdio>
#include <queue>
#include <cstring>

int dx[MAXN],Map_now[MAXS][MAXS],dream[MAXS][MAXS];
char inp[MAXS<<1];std::queue<int> que;bool ex[MAXN];
int opx[4]={0,0,1,-1};
int opy[4]={1,-1,0,0};

inline int Pos(int x,int y){
	return ((x-1)<<2)+y-1;
}

inline int Cal(int p[5][5]){
	int Ans=0;
	for(int i=1;i<5;i++) for(int j=1;j<5;j++) if(p[i][j]) Ans|=1<<Pos(i,j);
	return Ans;
}

int main(){
	for(int i=1;i<5;i++){scanf("%s",inp+1);for(int j=1;j<5;j++) Map_now[i][j]=inp[j]-'0';}
	for(int i=1;i<5;i++){scanf("%s",inp+1);for(int j=1;j<5;j++) dream[i][j]=inp[j]-'0';}
	memset(dx,50,sizeof(dx));int stat;dx[stat=Cal(Map_now)]=0;que.push(stat);
	while(!que.empty()){
		int p=que.front(),new_s;que.pop();ex[p]=false;
		for(int i=1;i<5;i++){
			for(int j=1;j<5;j++){
				int new_p=Pos(i,j);
				if(p&(1<<new_p)){
					for(int k=0;k<4;k++){
						int nx=i+opx[k],ny=j+opy[k];
						int rp=Pos(nx,ny);
						if(nx<1||nx>4) continue;
						if(ny<1||ny>4) continue;
						if((p&(1<<rp))==0){
							new_s=p;new_s^=1<<new_p;
							new_s|=1<<rp;
							if(dx[new_s]>dx[p]+1){
								dx[new_s]=dx[p]+1;
								if(!ex[new_s]){
									ex[new_s]=true;
									que.push(new_s);
								}
							}
						}
					}
				}
			}
		}
	}
	printf("%d",dx[Cal(dream)]);
	return 0;
}