题目大意
给两个素数a、b,要求每次只能改变一个数字并且最高位不能为0,而且每次变换后的数字也要为素数,求最少改几次能由a得到b。
分析
显然,打素数表,BFS即可。
具体为,4位数字,每次改变一位从0-9替换,判断是否满足,入队,直到==b
注意,不要忘记a==b时,替换后,要在复原回去。
AC Code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e4+10;
using namespace std;
bool prime[maxn],vis[maxn];
int a,b,cnt[maxn];
void isprime() {
prime[0] = prime[1] = false;
for(int i = 2 ; i < maxn ; i ++) prime[i] = true;
for(int i = 2 ; i*i <= maxn ; i ++) {
if(!prime[i]) continue;
for(int j = i*2 ; j < maxn ; j += i) {
prime[j] = false;
}
}
}
int bfs() {
memset(cnt,0,sizeof(cnt));
if(a==b)return cnt[a];
queue<int> q;
memset(vis,0,sizeof(vis));
int t[4],cur,next,tem;
q.push(a);
vis[a]=1;
int cas=1;
while(!q.empty()) {
cur=q.front();
q.pop();
t[0]=cur/1000;
t[1]=cur/100%10;
t[2]=cur/10%10;
t[3]=cur%10;
//printf("%d %d %d %d\n",t[0],t[1],t[2],t[3]);
for(int i=0; i<4; i++) {
tem=t[i];
for(int j=0; j<10; j++) { //use j <->t[i];
if(t[i]==j||(i==0&&j==0)) continue;
t[i]=j;
next=t[0]*1000+t[1]*100+t[2]*10+t[3];
if(prime[next]&&!vis[next]) {
cnt[next]=cnt[cur]+1;
vis[next]=1;
q.push(next);
}
if(next==b) return cnt[next];
}
t[i]=tem;
}
}
return -1;
}
int main() {
isprime();
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&a,&b);
printf("%d\n",bfs());
}
return 0;
}