HDU 1195 Open the Lock (双向广搜)


题意:给你初始4个数字和目标4个数字,问是否能由初始经过变换到目标数字;


变换规则:每个数字可以加1(9+1=1)或减1(1-1=9),或交换相邻的数字(最左和最右不是相邻的)。


双向广搜:分别对初始和目标数字进行广搜,vis数组用1和2标记两种已搜索的数字,用mp数组记录状态的步数。


当从前往后搜可以到达2或从后往前搜可以到达1状态则就可以了。。。


#include<stdio.h>
#include<string.h>
#include<string>
#include<queue>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;

struct node
{
	int a[4];
	int step;
}s,e;
int vis[10001];//标记当前状态是否有走过(从前往后走为1,从后往前走为2,没有走过为0)
int mp[10001];//标记走到当前状态的步数
int get_num(int c[])
{
	int n=0;
	for(int i=0;i<4;i++)
	{
		n*=10;
		n+=c[i];
	}
	return n;
}
int bfs()
{
	memset(vis,0,sizeof(vis));
	memset(mp,0,sizeof(mp));
	queue<node>p,q;
	int tmp;
	tmp=get_num(s.a);
	vis[tmp]=1;
	tmp=get_num(e.a);
	vis[tmp]=2;

	node u,v;
	p.push(s);
	q.push(e);
	while(!q.empty()||!p.empty())
	{
		if(!p.empty())
		{
			u=p.front();
			p.pop();
			for(int i=0;i<4;i++)
			{
				v=u;
				v.a[i]=u.a[i]+1;//+1
				if(v.a[i]==10)
					v.a[i]=1;
				tmp=get_num(v.a);
				if(vis[tmp]==0)//从前往后没有走过
				{
					v.step=u.step+1;
					mp[tmp]=v.step;//标记走到当前状态的步数
					vis[tmp]=1;
					p.push(v);
				}
				else if(vis[tmp]==2)//从前往后与从后往前有交叉
					return u.step+mp[tmp]+1;
				v.a[i]=u.a[i]-1;//-1
				if(v.a[i]==0)
					v.a[i]=9;
				tmp=get_num(v.a);
				if(vis[tmp]==0)
				{
					v.step=u.step+1;
					mp[tmp]=v.step;
					vis[tmp]=1;
					p.push(v);
				}
				else if(vis[tmp]==2)
					return u.step+mp[tmp]+1;
			}
			for(int i=0;i<3;i++)//交换
			{
				v=u;
				int k=v.a[i];
				v.a[i]=v.a[i+1];
				v.a[i+1]=k;
				tmp=get_num(v.a);
				if(vis[tmp]==0)
				{
					v.step=u.step+1;
					mp[tmp]=v.step;
					vis[tmp]=1;
					p.push(v);
				}
				else if(vis[tmp]==2)
					return u.step+mp[tmp]+1;
			}
			
		}
		if(!q.empty())
		{
			u=q.front();
			q.pop();
			for(int i=0;i<4;i++)
			{
				v=u;
				v.a[i]=u.a[i]+1;
				if(v.a[i]==10)
					v.a[i]=1;
				tmp=get_num(v.a);
				if(vis[tmp]==0)
				{
					v.step=u.step+1;
					mp[tmp]=v.step;
					vis[tmp]=2;
					q.push(v);
				}
				else if(vis[tmp]==1)//从后往前与从前往后哟交叉
					return u.step+mp[tmp]+1;
				
				v.a[i]=u.a[i]-1;
				if(v.a[i]==0)
					v.a[i]=9;
				tmp=get_num(v.a);
				if(vis[tmp]==0)
				{
					v.step=u.step+1;
					mp[tmp]=v.step;
					vis[tmp]=2;
					q.push(v);
				}
				else if(vis[tmp]==1)
					return u.step+mp[tmp]+1;
			}
			for(int i=0;i<3;i++)
			{
				v=u;
				int k=v.a[i];
				v.a[i]=v.a[i+1];
				v.a[i+1]=k;
				tmp=get_num(v.a);
				if(vis[tmp]==0)
				{
					v.step=u.step+1;
					mp[tmp]=v.step;
					vis[tmp]=2;
					q.push(v);
				}
				else if(vis[tmp]==1)
					return u.step+mp[tmp]+1;
			}
		}
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		char s1[10],s2[10];
		scanf("%s%s",s1,s2);
		for(int i=0;i<4;i++)
			s.a[i]=s1[i]-'0';
		for(int i=0;i<4;i++)
			e.a[i]=s2[i]-'0';
		s.step=0;
		e.step=0;
		printf("%d\n",bfs());
	}
	return 0;
}
/*
99
1221
1212
*/


你可能感兴趣的:(HDU 1195 Open the Lock (双向广搜))