()原题链接:
# 原题:POJ 3126 - Prime Path | 眈眈探求 # 解题思路:https://blog.csdn.net/LYHVOYAGE/article/details/18228531
一 注意技巧:
1. 这个题可以把“千百十个”的每一位当做一个轮子,每个轮子上有0-9十位数字;每次转动一个轮子,则得到一个新数值,即为当前节点的子节点。
2. 特别注意:
2.1 千位不能为0
2.2 个位不能为偶数
(详见获得子节点的函数Get_nodes)
二 代码实现
# POJ 3126 - Prime Path
# 原题:https://exp-blog.com/algorithm/poj/poj3126-prime-path/
# 解题思路:https://blog.csdn.net/LYHVOYAGE/article/details/18228531
import collections
## 计算素数个数
def NumofPrime(parent,target):
V = target
steps = 0
while V!=None:
# print(V)
V = parent[V]
steps += 1
return steps -1
## 判断是否为素数
def isPrime(temp0):
num = int(temp0)
for i in range(2,num//2+1):
if num%i == 0:
return False
return True
# ## 获取其邻接点
# def Get_nodes(vertex):
# s = vertex
# nodes = []
# for i in range(4):
# # temp = s[i]
# if i == 0:#首位不能是0
# # 上转
# if s[i] == '9':
# temp0 ='1'
# else:
# temp0 = str(int(s[i])+1)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
# # 下转
# if s[i] == '1':
# temp0 ='9'
# else:
# temp0 = str(int(s[i])-1)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
# elif i == 3:#末位不能是偶数
# # 上转
# if s[i] == '9':
# temp0 ='1'
# else:
# temp0 = str(int(s[i])+2)
# # 判断是否为素数
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
# # 下转
# if s[i] == '1':
# temp0 = '9'
# else:
# temp0 = str(int(s[i]) - 2)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
# else:
# # 上转
# if s[i] == '9':
# temp0 = '0'
# else:
# temp0 = str(int(s[i]) + 1)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
# # 下转
# if s[i] == '0':
# temp0 = '9'
# else:
# temp0 = str(int(s[i]) - 1)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
# return nodes
## 获取其邻接点
def Get_nodes(vertex):
s = vertex
nodes = []
for i in range(4):
# temp = s[i]
if i == 0:#首位不能是0
temp0 = s[i]
for zl in range(8):
# 上转-转动一圈:1-9
if temp0 == '9':
temp0 ='1' ## 特别注意,需要更新当前变量值
else:
temp0 = str(int(temp0)+1)
temp = s[:i] + temp0 + s[i + 1:]
if isPrime(temp): #判断是否为素数
nodes.append(temp)
# # 下转
# if s[i] == '1':
# temp0 ='9'
# else:
# temp0 = str(int(s[i])-1)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
elif i == 3:#末位不能是偶数:1 3 5 7 9
temp0 = s[i]
for zl in range(4):
# 上转一圈
if temp0 == '9':
temp0 ='1'
else:
temp0 = str(int(temp0)+2) #奇数
# 判断是否为素数
temp = s[:i] + temp0 + s[i + 1:]
if isPrime(temp):
nodes.append(temp)
# # 下转
# if s[i] == '1':
# temp0 = '9'
# else:
# temp0 = str(int(s[i]) - 2)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
else:
temp0 = s[i]
for zl in range(9):
# 上转-转动一圈:0 1 2 3 4 5 6 7 8 9
if temp0 == '9':
temp0 = '0'
else:
temp0 = str(int(temp0) + 1)
temp = s[:i] + temp0 + s[i + 1:]
if isPrime(temp):
nodes.append(temp)
# # 下转
# if s[i] == '0':
# temp0 = '9'
# else:
# temp0 = str(int(s[i]) - 1)
# temp = s[:i] + temp0 + s[i + 1:]
# if isPrime(temp):
# nodes.append(temp)
return nodes
## 子程序
def bfs(s,target):
if isPrime(s)== False or isPrime(target)== False: #如果起始点和目标点不是素数,则返回。。。
return "Impossible"
if s == target: #如果起始点和目标点相同,则返回。。。
return 0
# 设置队列,并将起始节点加入到队列中
queue = []
queue.append(s)
# 设置集合,存储访问节点:
visited = set()
visited.add(s)
# 设置字典,存储父节点
parent = collections.defaultdict(list)
parent[s] = None
# 开始执行吧
while len(queue)>0:
# 弹出节点:
vertex = queue.pop(0) # 特别注意,需要弹出前端节点,而不要错误写成.pop()
# 获取其邻接点:原理类似于转轮子,转动一周
nodes = Get_nodes(vertex)
# 判断邻接点是否为目标点
for i in nodes:
if i not in visited:
visited.add(i)
queue.append(i)
parent[i] = vertex
# 判断是否为目标点
if i == target:
return NumofPrime(parent,target)
return "Impossible"
## 输入n组【起始素数,目标素数】
n = int(input().strip())
inputs = []
for i in range(n):
# inputs.append(list(map(int,input().strip().split(' ')))) #这里要使用list:结果是int类型
inputs.append(input().strip().split(' ')) # 结果是字符串类型
print(inputs)
# 开始处理吧
for i in range(n):
s = inputs[i][0] #起始节点
target = inputs[i][1] #终止节点
# 执行相应的程序
ans = bfs(s,target) #返回最短路径
print(ans)
输入:
3
1033 8179
1373 8017
1033 1033
输出:
6
7
0