HDU 1195 BFS,双向BFS两种写法

Open the Lock

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1788    Accepted Submission(s): 747


Problem Description
Now an emergent task for you is to open a password lock. The password is consisted of four digits. Each digit is numbered from 1 to 9.
Each time, you can add or minus 1 to any digit. When add 1 to '9', the digit will change to be '1' and when minus 1 to '1', the digit will change to be '9'. You can also exchange the digit with its neighbor. Each action will take one step.

Now your task is to use minimal steps to open the lock.

Note: The leftmost digit is not the neighbor of the rightmost digit.
 

Input
The input file begins with an integer T, indicating the number of test cases.

Each test case begins with a four digit N, indicating the initial state of the password lock. Then followed a line with anotther four dight M, indicating the password which can open the lock. There is one blank line after each test case.
 

Output
For each test case, print the minimal steps in one line.
 

Sample Input
  
  
2 1234 2144 1111 9999
 

Sample Output
  
  
2 4
 

Author
YE, Kai
 

Source
 

Recommend
Ignatius.L
 


 

这个题,直接使用BFS爆搜是能够过得,31ms

这个题被挂在了我们学校的OJ,数据被一些邪恶的学弟们加强了。。我用了BFS然后果断TLE

题目链接:http://220.166.52.162/oj/showproblem?problem_id=2360

 

后来得知,需要使用双向BFS。很可惜,自己从未写过双向BFS。于是又跑到网上去看双向BFS的资料。总算看明白了。。(退役的半年里,第一次学习新的算法)

 

其实思路还是挺简单的,双向就是利用两个BFS拼在一起,一个从起点开始搜索,一个从终点开始搜索

当两个BFS搜索的轨迹有重合的部分的时候,立即停止两个BFS,并根据当前重合点的与两个BFS已得到的信息来计算答案。

 

贴下代码:(双向BFS也写的很挫,把队列换成数组之后才1000ms卡过去了,当然在HDU上是0ms)

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<stdlib.h>

using namespace std;

int A[5],B[5],aim;
int flag[10000];
int ak[10000];
int bk[10000];

struct node
{
	int num;
	int step;
};

void bfs()
{
	memset(flag,0,sizeof(flag));
	node k1,k2,k3,k4;
	int tmp[5],i,now[5],mt;
	node q1[10000];
	node q2[10000];
	int h1=0,t1=0,h2=0,t2=0;
	k1.num=A[1]*1000+A[2]*100+A[3]*10+A[4];
	flag[k1.num]=1;
	ak[k1.num]=0;
	k1.step=0;
	k3.num=B[1]*1000+B[2]*100+B[3]*10+B[4];
	k3.step=0;
	bk[k3.num]=0;
	flag[k3.num]=2;
	q1[t1++]=k1;
	q2[t2++]=k3;
	while(h1!=t1||h2!=t2)
	{
		int len1=t1-h1;
		while(len1--)
		{
			k2=q1[h1++];
			tmp[1]=k2.num/1000;
			tmp[2]=(k2.num%1000)/100;
			tmp[3]=(k2.num%100)/10;
			tmp[4]=k2.num%10;
			for(i=1;i<=4;i++)
			{
				now[1]=tmp[1];
				now[2]=tmp[2];
				now[3]=tmp[3];
				now[4]=tmp[4];
				now[i]=tmp[i]+1;
				if(now[i]==10)
					now[i]=1;
				mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
				if(flag[mt]==2)
				{
					printf("%d\n",k2.step+bk[mt]+1);
					return;
				}
				if(!flag[mt])
				{
					flag[mt]=1;
					k1.num=mt;
					k1.step=k2.step+1;
					ak[mt]=k1.step;
					q1[t1++]=k1;
				}
			}
			for(i=1;i<=4;i++)
			{
				now[1]=tmp[1];
				now[2]=tmp[2];
				now[3]=tmp[3];
				now[4]=tmp[4];
				now[i]=tmp[i]-1;
				if(now[i]==0)
					now[i]=9;
				mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
				if(flag[mt]==2)
				{
					printf("%d\n",k2.step+bk[mt]+1);
					return;
				}
				if(!flag[mt])
				{
					flag[mt]=1;
					k1.num=mt;
					k1.step=k2.step+1;
					ak[mt]=k1.step;
					q1[t1++]=k1;
				}
			}
			now[1]=tmp[2];
			now[2]=tmp[1];
			now[3]=tmp[3];
			now[4]=tmp[4];
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(flag[mt]==2)
			{
				printf("%d\n",k2.step+bk[mt]+1);
				return;
			}
			if(!flag[mt])
			{
				flag[mt]=1;
				k1.num=mt;
				k1.step=k2.step+1;
				ak[mt]=k1.step;
				q1[t1++]=k1;
			}
			now[1]=tmp[1];
			now[2]=tmp[3];
			now[3]=tmp[2];
			now[4]=tmp[4];
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(flag[mt]==2)
			{
				printf("%d\n",k2.step+bk[mt]+1);
				return;
			}
			if(!flag[mt])
			{
				flag[mt]=1;
				k1.num=mt;
				k1.step=k2.step+1;
				ak[mt]=k1.step;
				q1[t1++]=k1;
			}
			now[1]=tmp[1];
			now[2]=tmp[2];
			now[3]=tmp[4];
			now[4]=tmp[3];
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(flag[mt]==2)
			{
				printf("%d\n",k2.step+bk[mt]+1);
				return;
			}
			if(!flag[mt])
			{
				flag[mt]=1;
				k1.num=mt;
				k1.step=k2.step+1;
				ak[mt]=k1.step;
				q1[t1++]=k1;
			}
	//		printf("%d %d %d 1\n",k2.num,k2.step,ak[k2.num]);
	//		system("pause");
		}
		int len2=t2-h2;
		while(len2--)
		{
			k4=q2[h2++];
			tmp[1]=k4.num/1000;
			tmp[2]=(k4.num%1000)/100;
			tmp[3]=(k4.num%100)/10;
			tmp[4]=k4.num%10;
			for(i=1;i<=4;i++)
			{
				now[1]=tmp[1];
				now[2]=tmp[2];
				now[3]=tmp[3];
				now[4]=tmp[4];
				now[i]=tmp[i]+1;
				if(now[i]==10)
					now[i]=1;
				mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
				if(flag[mt]==1)
				{
					printf("%d\n",ak[mt]+k4.step+1);
					return;
				}
				if(!flag[mt])
				{
					flag[mt]=2;
					k3.num=mt;
					k3.step=k4.step+1;
					bk[mt]=k3.step;
					q2[t2++]=k3;
				}
			}
			for(i=1;i<=4;i++)
			{
				now[1]=tmp[1];
				now[2]=tmp[2];
				now[3]=tmp[3];
				now[4]=tmp[4];
				now[i]=tmp[i]-1;
				if(now[i]==0)
					now[i]=9;
				mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
		//		printf("%d %d\n",mt,ak[mt]);
				if(flag[mt]==1)
				{
					printf("%d\n",ak[mt]+k4.step+1);
					return;
				}
				if(!flag[mt])
				{
					flag[mt]=2;
					k3.num=mt;
					k3.step=k4.step+1;
					bk[mt]=k3.step;
					q2[t2++]=k3;
				}
			}
			now[1]=tmp[2];
			now[2]=tmp[1];
			now[3]=tmp[3];
			now[4]=tmp[4];
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(flag[mt]==1)
			{
				printf("%d\n",ak[mt]+k4.step+1);
				return;
			}
			if(!flag[mt])
			{
				flag[mt]=2;
				k3.num=mt;
				k3.step=k4.step+1;
				bk[mt]=k3.step;
				q2[t2++]=k3;
			}
			now[1]=tmp[1];
			now[2]=tmp[3];
			now[3]=tmp[2];
			now[4]=tmp[4];
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(flag[mt]==1)
			{
				printf("%d\n",ak[mt]+k4.step+1);
				return;
			}
			if(!flag[mt])
			{
				flag[mt]=2;
				k3.num=mt;
				k3.step=k4.step+1;
				bk[mt]=k3.step;
				q2[t2++]=k3;
			}
			now[1]=tmp[1];
			now[2]=tmp[2];
			now[3]=tmp[4];
			now[4]=tmp[3];
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(flag[mt]==1)
			{
				printf("%d\n",ak[mt]+k4.step+1);
				return;
			}
			if(!flag[mt])
			{
				flag[mt]=2;
				k3.num=mt;
				k3.step=k4.step+1;
				bk[mt]=k3.step;
				q2[t2++]=k3;
			}
	//		printf("%d %d %d 2\n",k4.num,k4.step,bk[k4.num]);
	//		system("pause");
		}
	}
}

int main()
{
	int t,tk,ts;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&tk);
		scanf("%d",&ts);
		if(tk==ts)
		{
			printf("0\n");
			continue;
		}
		A[1]=tk/1000;
		A[2]=(tk%1000)/100;
		A[3]=(tk%100)/10;
		A[4]=tk%10;
		B[1]=ts/1000;
		B[2]=(ts%1000)/100;
		B[3]=(ts%100)/10;
		B[4]=ts%10;
		aim=B[1]*1000+B[2]*100+B[3]*10+B[4];
		bfs();
	}
	return 0;
}



附录:

为了便于才学算法的新人,贴出本人TLE的单向BFS代码(HDU上31ms)

代码:

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>

using namespace std;

int A[5],B[5],aim;
bool flag[10000];

struct node
{
	int num;
	int step;
};

void bfs()
{
	memset(flag,0,sizeof(flag));
	node k1,k2;
	int tmp[5],i,now[5],mt;
	queue<node>q;
	k1.num=A[1]*1000+A[2]*100+A[3]*10+A[4];
	flag[k1.num]=true;
	k1.step=0;
	q.push(k1);
	while(!q.empty())
	{
		k2=q.front();
		q.pop();
		if(k2.num==aim)
		{
			printf("%d\n",k2.step);
			break;
		}
		tmp[1]=k2.num/1000;
		tmp[2]=(k2.num%1000)/100;
		tmp[3]=(k2.num%100)/10;
		tmp[4]=k2.num%10;
		for(i=1;i<=4;i++)
		{
			now[1]=tmp[1];
			now[2]=tmp[2];
			now[3]=tmp[3];
			now[4]=tmp[4];
			now[i]=tmp[i]+1;
			if(now[i]==10)
				now[i]=1;
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(!flag[mt])
			{
				flag[mt]=true;
				k1.num=mt;
				k1.step=k2.step+1;
				q.push(k1);
			}
		}
		for(i=1;i<=4;i++)
		{
			now[1]=tmp[1];
			now[2]=tmp[2];
			now[3]=tmp[3];
			now[4]=tmp[4];
			now[i]=tmp[i]-1;
			if(now[i]==0)
				now[i]=9;
			mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
			if(!flag[mt])
			{
				flag[mt]=true;
				k1.num=mt;
				k1.step=k2.step+1;
				q.push(k1);
			}
		}
		now[1]=tmp[2];
		now[2]=tmp[1];
		now[3]=tmp[3];
		now[4]=tmp[4];
		mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
		if(!flag[mt])
		{
			flag[mt]=true;
			k1.num=mt;
			k1.step=k2.step+1;
			q.push(k1);
		}
		now[1]=tmp[1];
		now[2]=tmp[3];
		now[3]=tmp[2];
		now[4]=tmp[4];
		mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
		if(!flag[mt])
		{
			flag[mt]=true;
			k1.num=mt;
			k1.step=k2.step+1;
			q.push(k1);
		}
		now[1]=tmp[1];
		now[2]=tmp[2];
		now[3]=tmp[4];
		now[4]=tmp[3];
		mt=now[1]*1000+now[2]*100+now[3]*10+now[4];
		if(!flag[mt])
		{
			flag[mt]=true;
			k1.num=mt;
			k1.step=k2.step+1;
			q.push(k1);
		}
	}
}

int main()
{
	int t,tk,ts;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&tk);
		scanf("%d",&ts);
		A[1]=tk/1000;
		A[2]=(tk%1000)/100;
		A[3]=(tk%100)/10;
		A[4]=tk%10;
		B[1]=ts/1000;
		B[2]=(ts%1000)/100;
		B[3]=(ts%100)/10;
		B[4]=ts%10;
		aim=B[1]*1000+B[2]*100+B[3]*10+B[4];
		bfs();
	}
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值