题目链接:点我啊╭(╯^╰)╮
题目大意:
给你两个四位数 a a a和 b b b,问从 a a a变换到 b b b需要几步,每步只能换一个数字,且改变的过程中必须保证这个数一直是素数???
解题思路:
一瞬间可能会想到枚举,但其实和枚举的思想差不多,每步变换的时候就BFS搜索,也就是求到目标的步数
代码思路:
首先打一个素数表,用于判断,然后对四个位进行搜索,每次搜索的思想就是BFS,记得改变数字的过程中进队后要变回来,因为前一位数字变了再判断后一位就不对了
核心:熟练地想到用BFS来进行判断
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool prime[10000];
int cnt[10000], vis[10000];
int BFS(int a, int b) {
queue <int> q;
q.push(a);
vis[a] = true;
int t[4];
while(!q.empty()) {
int n = q.front();
q.pop();
t[0] = n/1000;
t[1] = n%1000/100;
t[2] = n%100/10;
t[3] = n%10;
for(int i=0; i<4; i++) {
for(int j=0; j<10; j++) {
int ti = t[i];
if(j!=t[i]) {
t[i] = j;
int temp = t[0]*1000 + t[1]*100 + t[2]*10 + t[3];
if(!vis[temp] && prime[temp]) {
cnt[temp] = cnt[n]+1;
vis[temp] = true;
q.push(temp);
}
if(temp==b) return cnt[temp];
}
t[i] = ti; //注意这里要换回来,为了后面位置的判断
}
}
if(n==b) return cnt[n];
}
return -1;
}
int main() {
int n, a, b;
scanf("%d", &n);
for(int i=1000, j; i<=10000; i++) {
for(j=2; j<i; j++)
if(i%j==0) {
prime[i]=false;
break;
}
if(j==i) prime[i]=true;
}
while(n--) {
memset(cnt, 0, sizeof(cnt));
memset(vis, 0, sizeof(vis));
scanf("%d%d", &a, &b);
int ans = BFS(a, b);
if(ans!=-1) printf("%d\n", ans);
else printf("Impossible\n");
}
}