1054: [HAOI2008]移动玩具

1054: [HAOI2008]移动玩具

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 1514   Solved: 826
[ 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



强行bfs。。。
一开始忘记特判有点傻逼。。。
用二进制表示状态然后bfs应该不难

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;

const int maxn = 2 << 18;
const int dx[4] = {1,-1,4,-4};
typedef long long LL;

LL dis[maxn],a,b;
int i,j,s,t;

queue <int> q;

int main()
{
	#ifdef YZY
		freopen("yzy.txt","r",stdin);
	#endif
	
	int x;
	for (i = 1; i <= 4; i++)
	{
		cin >> x;
		a = a * 10000 + 1LL*x;
	}
	for (i = 1; i <= 4; i++)
	{
		cin >> x;
		b = b * 10000 + 1LL*x;
	}
	
	for (int l = 0; a; a /= 10,l++)
		if (a & 1) s += 1 << l;
	for (int l = 0; b; b /= 10,l++)
		if (b & 1) t += 1 << l;
	
	memset(dis,-1,sizeof(dis));
	dis[s] = 0;
	
	q.push(s);
	while (!q.empty())
	{
		int k = q.front();
		q.pop();
		int now = k,pos = 0;
		if (now == t)
		{
			cout << dis[now];
			return 0;
		}
		for (; now; now >>= 1,pos++)
		{
			if (now & 1)
			{
				for (int l = 0; l < 4; l++)
				{
					if (pos % 4 == 3 && l == 0) continue;
					if (pos % 4 == 0 && l == 1) continue;
					if (12 <= pos && pos < 16 && l == 2) continue;
					if (0 <= pos && pos < 4 && l == 3) continue;
					int T = 1 << (pos + dx[l]);
					if (k & T) continue;
					int to = k + T - (1 << pos);
					if (dis[to] == -1)
					{
						dis[to] = dis[k] + 1;
						q.push(to);
						if (to == t)
						{
							cout << dis[to];
							return 0;
						}
					}
				}
			}
		}
	}
	return 0;
}


你可能感兴趣的:(1054: [HAOI2008]移动玩具)