一、内容
题意:给定2个质数,代表开头和结尾,每次只能改变一位上的数字,且改变后的数也要是质数,求最少几次能变成结尾的数字。
二、思路
- 先筛选1000-9999的质数存在is_peime里面。
- bfs搜索将每位上的数字进行改变,枚举下所有情况,若改变后的数字是质数且未访问过就入队。
- 通过整除和取余得到某位上的数字,然后再修改成需要的数。
三、代码
#include <cstdio>
#include <queue>
#include <iostream>
#include <cstring>
using namespace std;
int is_prime[10005], st, end, n, vis[10005];
int help[4] = {1, 10, 100, 1000};
struct node {
int num, step;
node(int num, int step): num(num), step(step){}
};
void init() {
for (int i = 2; i * i <= 10000; i++) {
if (!is_prime[i]) {
for (int j = i * i; j <= 10000; j += i) {
is_prime[j] = 1;
}
}
}
}
int bfs() {
queue<node> q;
q.push(node(st, 0));
vis[st] = 1;
while (q.size()) {
node t = q.front();
q.pop();
//模拟下状态
for (int i = 0; i < 4; i++) {
//修改数字
int tem;
for (int j = (i == 3 ? 1 : 0); j <= 9; j++) {
tem = (j - (t.num / help[i] % 10)) * help[i] + t.num;
if (is_prime[tem] || vis[tem]) continue;
q.push(node(tem, t.step + 1));
vis[tem] = 1;
if (tem == end) return t.step + 1;
}
}
}
return -1;
}
int main() {
init();
scanf("%d", &n);
while (n--) {
memset(vis, 0, sizeof vis);
scanf("%d%d", &st, &end);
if (st == end) {
printf("0\n");
continue;
}
int t = bfs();
if (t != -1)
printf("%d\n", t);
else
printf("Impossible\n");
}
return 0;
}