题目描述:
读完题目大家有思路了吗?反正我有了:哪个**闲的没事干这b玩意,****。
整体思路算是比较暴力,就是将这个四位数的每一位都拆解开来,让每位都从0-9挨个换一遍,组成一个新的数字再将其判断是否为质数。
一个小坑:任意数字的首位不得为0,代码里特判一下就好。
想到这,思路就很清晰了,大概是一个筛质数+拆分数字+组合数字,因为题目要求是最小次数,所以就bfs直接搜索就行。
贴上代码:
#include <cstring>
#include <queue>
#include <string>
#include <iostream>
#include <map>
const int N = 100005;
int not_prime[N], a[10], vis[N], step[N];
void get_prime() {//质数筛
not_prime[0] = 1;
not_prime[1] = 1;
for (int i = 2; i < N; i++) {
if (!not_prime[i]) {
for (int j = 2 * i; j < N; j += i) {
not_prime[j] = true;
}
}
}
}
void solve() {
memset(vis, 0, sizeof vis);
memset(vis, 0, sizeof vis);
memset(step, 0, sizeof step);
std::queue<int> q;
int s, t; // 起始数字和目标数字
std::cin >> s >> t;
q.push(s);
vis[s] = 1;
while (!q.empty()) {//正常bfs队列
int f = q.front();
q.pop();
if (f == t) {
break;
}
int tf = f;
for (int i = 3; i >= 0; i--) { // 为了把数字f拆分成数位
// 1123
// a[0] = 1, a[1] = 1, a[2] = 2, a[3] = 3;
a[i] = f % 10;
f /= 10;
}
f = tf;
for (int i = 0; i < 4; i++) { // 枚举每一个数位,a[0], a[1], a[2], a[3]
int backup = a[i]; // 记录一下原来a[i]是什么数字
for (int j = 0; j < 10; j++) { // 枚举把a[i]这个数位变成什么数字
a[i] = j; // 把第i位变成j
int tt = 0; // 把第i位变成j之后,这个数字是什么
for (int k = 0; k < 4; k++) {
tt = tt * 10 + a[k];//重新组合
}
if (tt >= 1000 && !not_prime[tt] && !vis[tt]) {
// 首位是不是0,tt是不是质数,tt之前有没有被访问过
step[tt] = step[f] + 1;
// step[tt] 表示从起始数字s到数字tt需要几步变换
vis[tt] = 1;
q.push(tt);
}
}
a[i] = backup; // 把a[i]原来的数字恢复回去
}
}
if (!vis[t]) std::cout << "Impossible" << '\n';
else std::cout << step[t] << '\n';
}
int main() {
// freopen("in.txt", "r", stdin);
get_prime();
int T;
std::cin >> T;
while (T--) {
solve();//直接写在solve里方便整理,不会那么的乱
}
return 0;
}