1. 程式人生 > >HDU 1195 BFS,雙向BFS兩種寫法

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

後來得知,需要使用雙向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;
}