搜索---广度搜索---F - Prime Path

The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices. 
— It is a matter of security to change such things every now and then, to keep the enemy in the dark. 
— But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know! 
— I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door. 
— No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime! 
— I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds. 
— Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime. 

Now, the minister of finance, who had been eavesdropping, intervened.
— No unnecessary expenditure, please! I happen to know that the price of a digit is one pound. 
— Hmm, in that case I need a computer program to minimize the cost. You don't know some very cheap software gurus, do you? 
— In fact, I do. You see, there is this programming contest going on... Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above. 
1033 
1733 
3733 
3739 
3779 
8779 
8179
The cost of this solution is 6 pounds. Note that the digit 1 which got pasted over in step 2 can not be reused in the last step – a new 1 must be purchased.
Input
One line with a positive number: the number of test cases (at most 100). Then for each test case, one line with two numbers separated by a blank. Both numbers are four-digit primes (without leading zeros).
Output
One line for each case, either with a number stating the minimal cost or containing the word Impossible.
Sample Input
3
1033 8179
1373 8017
1033 1033
Sample Output
6
7
0

总结:

   该题目的大体意思是:给定两个素数n和m,要求把n变成m,每次变换时只能变一个数字,即变换后的数与变换前的数只有一个数字不同,并且要保证变换后的四位数也是素数。求最小的变换次数;如果不能完成变换,输出Impossible。因为不是求全部(全部的话用深搜),只是让求的变换后的数字与变化前的只有一位不相同,用广度搜索最为合适。

注意:

   1.bfs()最后返回的值,应当注意一下。例如题目中的第三个样例,是两个相同的数据输入时,输出的结果是0,那么此时就不可以将0作为函数的返回值。

  2.每一个新加入到队列中的vtemp,就是下一次while(!q.empty())里面新的v,count[v]的变化其实就是上一次的count[vtemp]。(只要队列不空while()循环一直进行,以1033 3733为例,它的while()循环就进行了1941次)

问题:

   1.下面代码是通过的,可是存在一个问题,加入将素数不进行打表而是进行单纯的判断,输出的结果就会存在问题。(将以下非注释部分换成注释部分就有问题,还请大家指教)

  

/*int isPrime(int m)
{
	int j;
	for(j=2;j<=m/2;j++)
		{
			if(m%j==0)
			{
				return 0;
			}
			 
		}

    if(j>m/2)	return 1;
} */
void init()
{
	int j,i;
	for(i=1000;i<10000;i++)
	{
		for(j=2;j<i;j++)
		{
			if(i%j==0)
			{
				vis[i]=false;
				break;
			}
		}
		if(j==i) vis[i]=true;
	}
}

  

做过单独的验证,真的没有发现这两个方法存在什么不同(可气):

  

#include<cstdio>
#include<iostream> 
#include<cstring>
#include<cmath>
using namespace std;
int num1[10005];
int num2[10005];
int f1=0;
int f2=0;
void init()
{
    int i,j;
	for(i=1000;i<=10000;i++)
	{
		for(j=2;j<i;j++)
		{
			if(i%j==0)
			{
			
				break;
			}
		}
		if(i==j)  num1[f1++]=i;
	}
}
void isprime()
{


	int i,j;
	for(i=1000;i<=10000;i++)
	{
		for(j=2;j<=sqrt(i);j++)
		{
			if(i%j==0)
			{
				break;
			}
		}
		if(j>sqrt(i))  num2[f2++]=i;
	}
}
int main()
{
	init();
	isprime();
	cout<<"f1="<<f1<<endl;
	cout<<"f2="<<f2<<endl;
	/*for(int i=0;i<=f1;i++)
	   cout<<"1:"<<num1[i]<<endl;
	for(int j=0;j<f2;j++)
	   cout<<"2:"<<num2[j]<<endl;*/
	return 0;
}

#include <iostream>
#include <queue>
#include<cstring> 
#include<cmath>
#include<cstdio>
using namespace std;
bool vis[10005];
/*int isPrime(int m)
{
	int j;
	for(j=2;j<=m/2;j++)
		{
			if(m%j==0)
			{
				return 0;
			}
			 
		}

    if(j>m/2)	return 1;
} */
void init()
{
	int j,i;
	for(i=1000;i<10000;i++)
	{
		for(j=2;j<i;j++)
		{
			if(i%j==0)
			{
				vis[i]=false;
				break;
			}
		}
		if(j==i) vis[i]=true;
	}
}
int bfs(int first,int last)
{
	bool dis[10005];
	queue <int>q;
	int v,i,j,temp,vtemp,count[10005],t[4];
	memset(dis,false,sizeof(dis));
	memset(count,0,sizeof(count));
	q.push(first);
	dis[first]=true;
	while(!q.empty())
	{
		v=q.front();
		q.pop();
	       t[0]=v/1000;
		t[1]=(v%1000)/100;
		t[2]=(v/10)%10;
		t[3]=v%10;
	for(j=0;j<4;j++)
	{
			temp=t[j];//下面会有变化,一定得保存
			for(i=0;i<10;i++)
				if(i!=temp)
				{
					t[j]=i;
					vtemp=t[0]*1000+t[1]*100+t[2]*10+t[3];
					if(!dis[vtemp] &&vis[vtemp])//isPrime(vtemp))
					{
						count[vtemp]=count[v]+1;
						dis[vtemp]=true;
					    //cout<<"j="<<j<<",i="<<i<<",vtemp="<<vtemp<<",count[vtemp]="<<count[vtemp]<<",v="<<v<<",count[v]="<<count[v]<<endl;
						q.push(vtemp);
					}
					if(vtemp==last) return count[vtemp];
				}
			t[j]=temp;
		}
		if(v==last) return count[v];
	}

	return -1;
}

int main()
{
	int n,num1,num2;
	init();
	cin>>n;
	while(n--)
	{
		cin>>num1>>num2;
		if(bfs(num1,num2)==-1)
		   cout<<"Impossible"<<endl;
		else
		  cout<<bfs(num1,num2)<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SSYITwin/article/details/80365796