POJ 3126 - Prime Path + Python(BFS)

本文详细解析了POJ3126-PrimePath问题,主要涉及素数路径的最短距离计算。解题思路包括将数字的每一位看作一个轮子,通过上转和下转生成素数子节点,重点处理首位不能为0和个位不能为偶数的情况。同时提供了优化的邻接点获取函数,以提高效率。通过广度优先搜索(BFS)算法,寻找从起点到终点的最短路径。
摘要由CSDN通过智能技术生成

()原题链接:

# 原题: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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值