hdoj1067 Gap(bfs+hash)

看注释吧

#include<stdio.h>
#include<iostream>
#include<queue>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;
typedef struct loc
{
	int x,y;
}loc;
typedef struct map//图 
{
	loc pos[48],gap[4];//各个值的坐标,空白处的坐标 
	string s;//序列顺序 
	int dis;//移动数 
}map;
char gra[4][8];//初始数组 
string c2s() 
{
	string s="";
	for(int i=0;i<4;i++)
	for(int j=0;j<8;j++)
    s+=gra[i][j];
	return s;
}
int hash1(string s)//给每一种图对应一个关键值,防重。 
{
	long long h=0;
	for(int i=0;i<32;i++)
	{
		h=(h<<1)+s[i];
	}
	return h%999991;
}
int vis[1000000];
string End="";
char ss[32]={11,12,13,14,15,16,17,0,21,22,23,24,25,26,27,0,31,32,33,34,35,36,37,0,41,42,43,44,45,46,47,0};
int Bfs()
{
	queue<map> q;
	loc temp,temp1;
	map now,then;
	int k=0,a,b;
	while(!q.empty())q.pop();
	string s1;
	for(int i=0;i<4;i++)
	for(int j=0;j<8;j++)//初始化 
	{
		temp.x=i;temp.y=j;
		if(gra[i][j]==0)now.gap[k++]=temp;
		else now.pos[gra[i][j]]=temp;
	}
    memset(vis,0,sizeof(vis));
	s1=c2s();now.s=s1;vis[hash1(now.s)]=1; 
	now.dis=1;
	q.push(now);
	int e;e=hash1(End);
	while(!q.empty()&&!vis[e])
	{
		now=q.front();q.pop();
		then=now;then.dis=now.dis+1;
		for(int i=0;i<4;i++)//四种改变的可能 
		{
			temp=then.gap[i];
			a=8*temp.x+temp.y-1;
			if(then.s[a]%10==7||then.s[a]==0)continue;//尾数为7和为空白处不可进行移动操作,直接跳过。 
			temp1=then.pos[then.s[a]+1];
			b=temp1.x*8+temp1.y;
			swap(then.s[a+1],then.s[b]);//改变序列 
            k=hash1(then.s);	
			if(!vis[k])
			{
				if(k==e)return then.dis-1;
				then.gap[i]=temp1;
	            then.pos[then.s[a+1]]=temp;
	            q.push(then);
	            vis[k]=1;
	            then.gap[i]=temp;
	            then.pos[then.s[a+1]]=temp1;
			}
			swap(then.s[a+1],then.s[b]);//恢复原来状态	
		}
	}
	return vis[e]-1;
}
int main()
{
	int i,a;
	for(i=0;i<32;i++)End+=ss[i];
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(gra,0,sizeof(gra)); 
		for(int j=0;j<4;j++)
		for(int k=1;k<8;k++)
		{
		  scanf("%d",&a);
		  gra[j][k]=(char)a;  
          if(a%10==1) swap(gra[j][k],gra[(a/10)-1][0]);  //把11,21,31,41挑出放在最左边 
		}
		printf("%d\n",Bfs());
		//if(t>0)printf("\n");
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值