POJ 3126 Prime Path (bfs+欧拉线性素数筛)

时间:2022-03-15 16:48:14

Description

POJ 3126 Prime Path (bfs+欧拉线性素数筛)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 题意给你两个4位素数a b,让你将a每次改变一位数字,改变后的4位数还必须是素数,最少几步能变到b,输出步数,不能变到输出Impossible。
这题第一发T了...一看就是果然T,忘了加vis2这个数组标记那些数组被访问过了...不加的话因为队列及时pop了,会出现在两个素数之间来回跳的情况!
小插曲就是欧拉线性素数筛,自己还没背会2333333。
代码如下:
 #include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
#define inf 0x3f3f3f3f
int prime[],a,b,ans;
bool num[],vis[],vis2[];
bool flag;
int dig[];
struct node
{
int x,stp;
};
void split (int x)//将x分成各个位
{
for (int i=;i<;++i)
{
dig[i]=x%;
x/=;
}
}
int getnum (int a,int b,int c,int d)//将4个数字组成一个四位数
{
return a+b*+c*+d*;
}
void getprime()//欧拉线性素数筛
{
memset(num,false,sizeof num);
memset(vis,false,sizeof vis);
memset(prime,,sizeof prime);
int cnt=;
for (int i=;i<;++i)
{
if (!vis[i])
prime[cnt++]=i,num[i]=;
for (int j=;j<cnt&&i*prime[j]<;++j)
{
vis[i*prime[j]]=;
if (i%prime[j]==)
break;
}
}
}
void bfs(node now)
{
queue<node>q;
q.push(now);
vis2[now.x]=true;
if (now.x==b)
{
flag=true;
ans=now.stp;
return ;
}
while (!q.empty())
{
node frt=q.front();
q.pop();
if (frt.x==b)
{
flag=true;
ans=frt.stp;
return ;
}
split(frt.x);
for (int i=;i<=;++i)//改个位
{
int temp=getnum(i,dig[],dig[],dig[]);
if (temp==frt.x)
continue;
if (num[temp]&&!vis2[temp])
{
node tp;
tp.x=temp;
tp.stp=frt.stp+;
vis2[temp]=true;
q.push(tp);
}
}
for (int i=;i<=;++i)//改十位
{
int temp=getnum(dig[],i,dig[],dig[]);
if (temp==frt.x)
continue;
if (num[temp]&&!vis2[temp])
{
node tp;
tp.x=temp;
tp.stp=frt.stp+;
vis2[temp]=true;
q.push(tp);
}
}
for (int i=;i<=;++i)//改百位
{
int temp=getnum(dig[],dig[],i,dig[]);
if (temp==frt.x)
continue;
if (num[temp]&&!vis2[temp])
{
node tp;
tp.x=temp;
tp.stp=frt.stp+;
vis2[temp]=true;
q.push(tp);
}
}
for (int i=;i<=;++i)//改千位,注意是4位数,所以千位不为0,从一开始
{
int temp=getnum(dig[],dig[],dig[],i);
if (temp==frt.x)
continue;
if (num[temp]&&!vis2[temp])
{
node tp;
tp.x=temp;
tp.stp=frt.stp+;
vis2[temp]=true;
q.push(tp);
}
}
}
return ;
}
int main()
{
getprime();
//freopen("de.txt","r",stdin);
int t;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&a,&b);
memset(vis2,false,sizeof vis2);
ans=inf;
node now;
now.x=a,now.stp=;
bfs(now);
if (flag)
printf("%d\n",ans);
else
printf("Impossible\n");
}
return ;
}