Prime Path(BFS搜索)

题目连接: Prime Path

题目:

给你两个四位的素数a,b。
a可以改变某一位上的数字变成c,但只有当c也是四位的素数时才能进行这种改变。
请你计算a最少经过多少次上述变换才能变成b。
例如:1033 -> 8179
1033 -> 1733 -> 3733 -> 3739 -> 3779 ->8779 -> 8179
最少变换了6次。

Input
第一行输入整数T,表示样例数。 (T <= 100)
每个样例输入两个四位的素数a,b。(没有前导零)

Output
对于每个样例,输出最少变换次数,如果无法变换成b则输出"Impossible"。

Sample Input
3
1033 8179
1373 8017
1033 1033
Sample Output
6
7
0

解题思路:

BFS思想, 将最开始的那个数字每一位尝试0-9(首位1-9)变换, 如果变换后仍为素数, 推入队列, 直到队列空或者达到目标数字.

AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool num[10005]; //用于记录1000-9999各个数字是否为质数, 1是 0不是
bool vis[10005]; //用于记录当前数字是否已经出现过
int n, m; int ans;  //初始数字m, 目标数字n, 变化次数ans
queue<int> q;
void first() //预处理操作, 把1000-9999内素数进行标记
{
	for (int i = 1000; i <= 9999; i++) {
		for (int j = 2; j <= sqrt(i); j++) {
			if (i % j == 0) goto here;
		}
		num[i] = 1;
	here:;
	}
}
//1033 / 100 = 10  1033 % 100 = 33
bool fact() //BFS
{
	ans = -1; //至于为什么一开始标记成-1, 请想一下
	while (!q.empty()) {
		int t = q.size(); ans++; //每次循环原先队列有的元素, 即保证当前层的元素都是上一步变化产生的
		while (t--) {
			int op = q.front(); q.pop();
			if (op == m) return 1;
			int temp; //for循环处的代码就是分别改变 千位 百位 十位 个位的数字, 如果改变后的数字是质数且未出现, 则推入队列
			for (int i = 0; i <= 9; i++) {
				if (i != 0) { //千位特判
					temp = i * 1000 + op % 1000;
					if (!vis[temp] && num[temp]) { q.push(temp); vis[temp] = 1; }
				}
				temp = i * 100 + op % 100 + op / 1000 * 1000;
				if (!vis[temp] && num[temp]) { q.push(temp); vis[temp] = 1; }
				temp = i * 10 + op % 10 + op / 100 * 100;
				if (!vis[temp] && num[temp]) { q.push(temp); vis[temp] = 1; }
				temp = i + op / 10 * 10;
				if (!vis[temp] && num[temp]) { q.push(temp); vis[temp] = 1; }
			}
		}
	}
	return 0; //队列已空, 无法得到目标数字
}

int main(void)
{
	first(); //预处理
	int t; cin >> t;
	while (t--) {
		memset(vis, 0, sizeof(vis)); while (!q.empty()) q.pop();
		scanf("%d %d", &n, &m);  vis[n] = 1;
		q.push(n);
		if (fact()) cout << ans << endl;
		else cout << "Impossible" << endl;
	}
	return 0;
}

如果不理解fact()函数中跑当前层的操作, 可以考虑改成结构体, 在其内加一个int step;表示当前操作次数, 当操作到这个数字时, 让得到的新数字的step’ = step+1, 最后输出得到目标数字时的step值也可.

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值