一、内容

题意:给定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;
}