题目:
给你两个四位的素数 a,ba,b 。 aa 可以改变某一位上的数字变成 cc ,但只有当 cc 也是四位的素数时才能进行这种改变。 请你计算 aa 最少经过多少次上述变换才能变成 bb 。 例如:1033 -> 8179 1033 1733 3733 3739 3779 8779 8179 最少变换了6次。
输入格式
第一行输入整数 TT ,表示样例数。 (T \le 100)(T≤100) 每个样例输入两个四位的素数 a, ba,b 。(没有前导零)
输出格式
对于每个样例,输出最少变换次数,如果无法变换成 bb 则输出"Impossible"。
注意:仅对于此题,输出时每行末尾的多余空格,不影响答案正确性。
输入样例
3 1033 8179 1373 8017 1033 1033
输出样例
6 7 0
这道题相当于广搜的四个方向,即把四位数的每个数位走一遍,先把四位的素数打个表再写
代码:
#include<stdio.h>
#include<string.h>
#include<queue>
#define N 10100
using namespace std;
int n,st,en;
bool book[N];
bool ss[N];
struct node {
int step;
int num;
};
void init() // 素数打表
{
for(int i=2; i<10000; i++) {
if(ss[i])continue;
for(int j=i+i; j<10000; j+=i) {
ss[j]=true;
}
}
}
void bfs()
{
memset(book,0,sizeof(book));
queue<node>q;
node x;
//存开始的那个数即为“起点”
x.num=st;
x.step=0;//此时步数即变换次数为0
book[x.num]=true;//标记已经走过
q.push(x);//存入队列
while(!q.empty())
{
//把队列中的元素提出来并清除
node x=q.front();
q.pop();
if(x.num==en) //如果已经找到或着说到达要变幻的素数就输出此时步数
{
printf("%d\n",x.step);
return ;
}
for(int i=0; i<4; i++) //四位数每个数位都要从1到9走一遍
{
for(int j=0; j<10; j++)
{
if(!i&&!j)
continue;
node y;//y为x的下一步
y.step=x.step+1;
int a=x.num/1000;
int b=x.num%1000/100;
int c=x.num%100/10;
int d=x.num%10;
if(i==0)
a=j;
else if(i==1)
b=j;
else if(i==2)
c=j;
else if(i==3)
d=j;
y.num=a*1000+b*100+c*10+d;
//判断y这个数是不是素数
if(book[y.num]||ss[y.num])
continue;
book[y.num]=true;//标记走过
q.push(y);//存入队列方便下一次取出
}
}
}
}
int main() {
init();
scanf("%d",&n);
while(n--) {
scanf("%d%d",&st,&en);
bfs();
}
return 0;
}