题目大意:求一个四位数素数转化为另外一个四位数素数需要更改多少步,一次只能转换一位数,并且转换之后的另外一个四位数也为素数。使用BFS+素数筛即可解决问题
eg:从1033->8179
1033
1733
3733
3739
3779
8779
8179
共6步
直接给出代码,在poj中好像AC不了,之后会更新修改后AC的代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
//#define mytest
//储存当前素数,与转换到当前素数所经过的步数
struct node{
int x,step;
};
bool vis[10010],flag[10010];
int prime[10010];
int cnum[10010],cnt = 0;
int n,p,q;
//埃氏筛
void E_sieve(){
memset(vis,false,sizeof(vis));
for(int i = 2;i*i<=10000;i++){
if(!vis[i]){
for(int j = i * i;j<=10000;j+=i){
vis[j] = true;
}
}
}
//将四位素数储存在cnum中
int k = 0;
for(int i = 2;i<=10000;i++){
if(!vis[i]){
if(i>1000){
cnum[cnt++] = i;
//cout<<i<<endl;
}
}
}
}
//检查下一个素数是否能由当前素数经过一次变化得出
bool check(int a,int b){
int sum = 0;
while(a){
//如果a%10不等于b%10,sum++
if(a%10 != b%10){
sum++;
}
a = a/10;
b = b/10;
}
//sum=1,说明可以一步变换得到
if(sum == 1)
return true;
return false;
}
int BFS(){
//flag用于标记次素数是否被标记过
memset(flag,false,sizeof(flag));
//当前素数,现在素数,下一个素数
node start,now,next;
queue<node> que;
start.x = p;
start.step = 0;
que.push(start);
while(!que.empty()){
now = que.front();
que.pop();
if(now.x == q){
return now.step;
}
//对所有四位的素数进行判断,能经过一次变化就得出的素数则入队。
for(int i = cnt - 1;i>=0;i--){
next = now;
//如果当前素数没有被标记过,且能一步由上一素数转换过来就入队
//并且进行标记
//如果被标记过则说明在此前已经有更短的步数转换到此素数。
if(!flag[cnum[i]] && check(next.x,cnum[i])){
//对当前素数进行标记
flag[cnum[i]] = true;
next.x = cnum[i];
//步数+1
next.step = now.step++;
//cout<<next.x<<endl;
que.push(next);
}
}
}
return -1;
}
int main(){
#ifdef mytest
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
cin>>n;
E_sieve();
while(n--){
cin>>p>>q;
int ans = BFS();
if(ans == -1)
cout<<"Impossible"<<endl;
else
cout<<ans<<endl;
}
return 0;
}