POJ - 3126 Prime Path (kuangbin - 简单搜索)

题目描述(已转换成中文)

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

输入格式

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

输出格式

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

输入输出样例
输入

3
1033 8179
1373 8017
1033 1033

输出

6
7
0

题目链接

分析:

  一个四位素数改变它四个位上的某一个数,变成另一个四位素数,这种操作称为:我们对原来的素数进行了一次变换。这道题就是求一个四位素数a变换成一个四位素数b所要进行的最少变换次数,要求每一次变换之后,得到新的四位数也是素数。
  所以我们先要打表求出四位数中的素数(这道题我用的是埃氏筛,其实常见还是用欧拉筛,都行)。主函数内输入样例数,再分别输入每组的两个素数,输入素数之前清零vis数组(标记某个素数是否之前通过变换出现过),如果输入的a和b相同,则不进行操作,直接输出0;否则调用bfs函数。
  bfs(a, b)函数内,先把原来的节点压入队列(x是素数的具体值,s是已经变换了的次数),之后分别对队首元素的个位、十位、百位、千位进行变换。用临时变量u表示变换后的四位数,check[u]是标记u是否为素数(之前通过init()函数打表得到的),之后对u进行一系列判断,若u是第一次被变换得到,并且是素数,就把新的节点m(m表示u的具体值和变换次数)压入队列,并且vis[u] = 1。直到u == b,输出从a到u的变换次数,并且直接返回,结束bfs函数;如果队列已经空了,还没找到要得到的四位素数,输出Impossible。

这道题需要注意的地方:

  大家可能有这种思想:我直接把原素数四个位的数字直接替换成b四个位上的数不就好了,这样不就最多变换四次就得到了吗?其实,这道题要求我们变换过程中得到的中间数也要是素数,所以我们在依次替换a的每个位上的数的过程中,得到的中间数可能不是素数,这是不符合条件的,所以还是乖乖bfs吧,这种题不会这么沙雕的hhhh
  对个位的数字进行变换的时候,个位数不用变成偶数(个位数是偶数的四位数必不是素数),这样就可以减少一些操作。并且在变换的时候,因为是通过for循环改变某个位上的数,所以还要判断每一次变换得到的数与它变换前的前一个数是否相等,不然相当于没变换。

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
int read(){
   
	int x, f = 1;
	char ch;
	while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
	x = ch - '0';
	while(ch = getchar(), ch >= '0' && ch <= '9') x =
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值