BZOJ1054 移动玩具 BFS+hash

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


    分析:dalao都说是水题,但我是真的不知道还有这种姿势的暴搜,涨见识了。这道题感觉来当hash+bfs的模板题好像很合适的样子。好了hash+bfs,其实就是把队列中的存点改成存图,只要队列中存到与答案相同的图,就一定是最优的(广搜性质不用说吧),至于如何判断是否与要求一样,或者是这张图走过没有,就直接给每张图个hash值每次判断是否为true就好了(map要开始装b了)

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <cmath>
# include <list>
# include <queue>
# include <map>
using namespace std;
typedef long long ll;
int read()
{
	int f=1,i=0;char ch=getchar();
	while(ch<'0'||ch>'9') 
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		i=(i<<3)+(i<<1)+ch-'0';
		ch=getchar();
	}
	return f*i;
}
struct data
{
	int a[5][5];
	int step;
}q[1000005];
struct node
{
	int x,y;
	node(){}
	node(int x,int y) : x(x),y(y){}
};
char ch[5][5];
int a[5][5],b[5][5],ans,s,t;
map<ll,bool>hash;
int judge(int a[5][5])
{
	int k=1,sum=0;
	for(int i=1;i<=4;++i)
	    for(int j=1;j<=4;++j)
	        {sum+=k*a[i][j];k<<=1;}
	return sum;    
}
node go(node p,int i)
{
	if(i==1) p.x--;
	if(i==2) p.x++;
	if(i==3) p.y--;
	if(i==4) p.y++;
	return p;
}
inline void BFS(int t)
{
    int head=0,tail=1;
	while(head<tail)
	{
	    for(int i=1;i<=4;++i)
	        for(int j=1;j<=4;++j)
	            if(q[head].a[i][j])
	                for(int k=1;k<=4;++k)
	                {
	                	node now=go(node(i,j),k);
	                	if(now.x<1||now.x>4||now.y<1||now.y>4||q[head].a[now.x][now.y]) continue;
	                        swap(q[head].a[i][j],q[head].a[now.x][now.y]);
	                	int flag=judge(q[head].a);
				if(!hash[flag])
	                	{
	                	    if(flag==t) 
	                	    {
	                		    printf("%d\n",q[head].step+1);
	                		    return;
	                	    }
	                	    hash[judge(q[head].a)]=1;
				    memcpy(q[tail].a,q[head].a,sizeof(q[tail].a));
	                	    q[tail].step=q[head].step+1;
	                	    ++tail;
	                	}
	                	swap(q[head].a[i][j],q[head].a[now.x][now.y]);
	                }
	       ++head;
	}
	
}
int main()
{
	
	for(int i=1;i<=4;++i)
	{
		scanf("%s",ch[i]);
		for(int j=0;j<4;++j)
		    q[0].a[i][j+1]=ch[i][j]-'0';    
	}
	for(int i=1;i<=4;++i)
	{
	    scanf("%s",ch[i]);
		for(int j=0;j<4;++j)
		    b[i][j+1]=ch[i][j]-'0';    
	}
	s=judge(q[0].a),t=judge(b);
	if(s==t) 
	{
	    printf("0\n");return 0;
	}
        hash[s]=1;BFS(t);
}
那个说一下,memecpy比for循环赋值快,所以搜到新图直接cpy就好了。好像有dalao跑了spfa?还有这种操作?感觉好高级的样子,有兴趣可以去搜一搜。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值