Description
内阁的部长们对于安全部门首脑声称要改变他们办公室的4个房间号非常烦恼。
—这只是一件安全措置,不时地改变这样的事物,使得敌人处于盲区。
— 但是你看,我已经选了我的房间号1033有很好的理由,我是总理,你知道的。
— 我知道的,所以你的新房间号8179也是素数,你只要在你的办公室房门上将这新的4位数字贴在老的4位数字上就可以了。
— 不,不那么简单。假如我把第一个数字改成8,那么数字8033就不是素数!
— 我知道,作为总理,你不能忍受一个非素数作为你的房间号即使只有几秒钟。
— 正确!我必须找到一个从1033到8179的一个素数路径的方案,从一个素数到下一个素数只要改变一位数。
一直在听的财政部长,也介入了讨论。
— 请不要产生不必要的开支!我碰巧知道,改一位数字的价格是1英镑。
— 在这种情况下,我需要一个计算机程序使得花费最小化,你知道有非常便宜的软件开发者吗?
— 我知道。有个程序设计竞赛马上要进行了。让他们帮助总理在两个四位素数之间找到最便宜的素数路径。当然,第一位是非零的。上述实例有个解答:
1033
1733
3733
3739
3779
8779
8179
这个解答花费6英镑。注意第1个位置在第2步被粘贴,在最后一步不能被重用,在第1个位置上要粘贴新值必须购买。
Input
第一行给出一个正整数:测试用例的数目(最多100)。每个测试用例一行,两个用空格分开的数字,这两个数字都是4位素数(不以0作为首位)。
Output
对于每个测试用例,输出一行,或者是最小花费的数目,或者输出Impossible。
Sample Input
3
1033 8179
1373 8017
1033 1033
Sample Output
6
7
0
思路:
用bfs实现。
获取队头元素,数位分离,枚举所有可拓展情况,每种情况判断是否为素数,如果是且没有访问过则入队。
当然千位不能是0。
代码:
#include<iostream>
#include<queue>
using namespace std;
struct data
{
int num,ans;
};
queue<data> q;
int n,start,last,minn=99999999;
bool vis[10001];
bool prime(int number)
{
for(int i=2;i*i<=number;i++)
if(number%i==0)return false;
return true;
}
int main()
{
cin>>n;
for(int k=1;k<=n;k++)
{
cin>>start>>last;
if(start==last)
{
cout<<"0"<<endl;
continue;
}
bool flag=false;
q.push((data){start,0});
vis[start]=true;
while(!q.empty())
{
data u=q.front();
q.pop();
if(u.num==last)
{
flag=true;
minn=min(u.ans,minn);
continue;
}
int di[4];
di[0]=u.num%10;//个
di[1]=u.num/10%10;//十
di[2]=u.num/100%10;//百
di[3]=u.num/1000;//千
for(int i=0;i<4;i++)
{
for(int j=0;j<=9;j++)
{
if(i==3&&j==0)continue;
int temp=di[i];
di[i]=j;
int number=di[0]+di[1]*10+di[2]*100+di[3]*1000;
if(prime(number)&&!vis[number])
{
q.push((data){number,u.ans+1});
vis[number]=true;
}
di[i]=temp;
}
}
}
if(flag)cout<<minn<<endl;
else cout<<"Impossible"<<endl;
for(int i=1000;i<=9999;i++)
vis[i]=false;
minn=99999999;
}
return 0;
}