分支限界法解布线问题Python实现

印刷电路板将布线区域分为n*m个方阵阵列,如图所示。精确的电路部分问题要求确定方格a的中点到方格b的中点的最短布线方案。在布线时,电路只能沿着直线或者直角布线,如图b所示。为了避免线路相交,已经布了线的方格做了封锁标记,其他线路不允许穿过被封锁的方格。
在这里插入图片描述
一个布线例子
思路主要时利用分支限界法,首先将起始点作为当前活结点,寻找活结点四周可以布线的点加入队列作为下一个拓展结点。
后弹出队列第一个元素作为当前活结点继续寻找拓展结点,循环直至找到终点或者队列为空(表示无解)

import numpy as np
from queue import Queue


class Position(object):
    def __init__(self, row, col):
        self.row = row
        self.col = col


def FindPath(start, finish, n, m, grid):  # 起始点,结束点,路径长,路径
    global path, PathLen1
    if start.row == finish.row and start.col == finish.col:
        Pathlen = 0
        return True
    grid[0, 0:m + 1] = grid[n + 1, 0:m + 1] = 1  # 设置四周的围墙
    grid[0:n + 1, 0] = grid[0:n + 1, m + 1] = 1
    offset = [Position(0, 1), Position(1, 0), Position(0, -1), Position(-1, 0)]  # 右,下,左,上
    NumofNbers = 4
    here = start
    nbr = Position(0, 0)
    grid[start.row][start.col] = 2
    Q = Queue(maxsize=0)  # 创建一个队列
    while True:
        for i in range(NumofNbers):  # 当前点的四周的点
            nbr.row = here.row + offset[i].row
            nbr.col = here.col + offset[i].col
            if grid[nbr.row, nbr.col] == 0:  # 该方格未被标记
                grid[nbr.row, nbr.col] = grid[here.row, here.col] + 1
                if nbr.row == finish.row and nbr.col == finish.col:  # 完成布线直接结束循环
                    break
                nbr1 = Position(nbr.row, nbr.col)
                Q.put(nbr1)  # 将当前点加入队列
        if nbr.row == finish.row and nbr.col == finish.col:  # 完成布线结束循环
            break
        if Q.empty():  # 队列为空,表示无解
            return False
        here = Q.get()  # 下一个拓展结点
    Pathlen = grid[finish.row, finish.col] - 2
    PathLen1 = Pathlen
    here = finish
    for j in range(Pathlen - 1, -1, -1):  # 回溯寻找路径
        path.append(Position(here.row, here.col))  # 将当前点加入路径
        for i in range(NumofNbers):
            nbr.row = here.row + offset[i].row
            nbr.col = here.col + offset[i].col
            if grid[nbr.row, nbr.col] == j + 2:  # 找到上一个坐标
                break
        here = Position(nbr.row, nbr.col)  # 更新为上一个坐标
    return True


def main():
    global path, PathLen1
    print("请输入方阵的行数和列数:", end='\n')
    n, m = map(int, input().split(' '))
    grid = np.zeros((n + 2, m + 2), dtype=int)
    print("请输入方阵,不能通过的地方输入1,能通过的地方输入0:")
    for i in range(1, n + 1):
        grid[i, 1:n + 1] = np.array(input().split(), dtype=int)
    print("请输入起点坐标:", end='\n')
    start_x, start_y = map(int, input().split(' '))
    print("请输入终点坐标:", end='\n')
    finish_x, finish_y = map(int, input().split(' '))
    start = Position(start_x, start_y)
    finish = Position(finish_x, finish_y)
    if FindPath(start, finish, n, m, grid):
        print("线路长: ", PathLen1)
        path.append(start)
        path = np.flipud(path)
        for i in range(len(path) - 1):
            print(path[i].row, end=',')
            print(path[i].col, end='-->')
        print(path[-1].row, end=',')
        print(path[-1].col)
    else:
        print("没有路径!")


global path, PathLen1
PathLen1 = 0  # 用于保存路线长度
path = []  # 保存路线
if __name__ == '__main__':
    main()


运行结果:

请输入方阵的行数和列数:
7 7
请输入方阵,不能通过的地方输入1,能通过的地方输入0:
0 0 1 0 0 0 0
0 0 1 1 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 0 0
1 0 0 0 1 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
请输入起点坐标:
3 2
请输入终点坐标:
4 6
线路长:  9
3,2-->4,2-->5,2-->5,3-->5,4-->6,4-->6,5-->6,6-->5,6-->4,6

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
布线问题是指在电路板上布置电路元件并连接它们的问题。Python可以使用分支界限算法解决布线问题。以下是Python实现布线问题的步骤: 1. 定义电路板的大小和障碍物的位置。 2. 定义起点和终点的位置。 3. 使用分支界限算法来搜索最短路径。 4. 输出路径和路径长度。 具体实现可以参考以下代码: ``` import queue class Point: def __init__(self, x, y): self.x = x self.y = y class Node: def __init__(self, point, parent=None): self.point = point self.parent = parent self.g = 0 self.h = 0 self.f = 0 def __eq__(self, other): return self.point.x == other.point.x and self.point.y == other.point.y def get_neighbors(point, obstacles, rows, cols): neighbors = [] if point.x > 0 and obstacles[point.x-1][point.y] == 0: neighbors.append(Point(point.x-1, point.y)) if point.x < rows-1 and obstacles[point.x+1][point.y] == 0: neighbors.append(Point(point.x+1, point.y)) if point.y > 0 and obstacles[point.x][point.y-1] == 0: neighbors.append(Point(point.x, point.y-1)) if point.y < cols-1 and obstacles[point.x][point.y+1] == 0: neighbors.append(Point(point.x, point.y+1)) return neighbors def get_path(current_node): path = [] while current_node is not None: path.append(current_node.point) current_node = current_node.parent return list(reversed(path)) def a_star(start, end, obstacles, rows, cols): start_node = Node(start) end_node = Node(end) open_list = queue.PriorityQueue() open_list.put((start_node.f, start_node)) closed_list = set() while not open_list.empty(): current_node = open_list.get()[1] if current_node == end_node: return get_path(current_node) closed_list.add(current_node) for neighbor in get_neighbors(current_node.point, obstacles, rows, cols): neighbor_node = Node(neighbor, current_node) if neighbor_node in closed_list: continue neighbor_node.g = current_node.g + 1 neighbor_node.h = abs(neighbor_node.point.x - end_node.point.x) + abs(neighbor_node.point.y - end_node.point.y) neighbor_node.f = neighbor_node.g + neighbor_node.h if any(open_node.f <= neighbor_node.f and open_node.point == neighbor_node.point for _, open_node in open_list.queue): continue open_list.put((neighbor_node.f, neighbor_node)) return None if __name__ == '__main__': rows = int(input("请输入方阵的行数和列数:")) cols = int(input()) obstacles = [] for i in range(rows): row = list(map(int, input("请输入第{}行的数据:".format(i+1)).split())) obstacles.append(row) start_x, start_y = map(int, input("请输入起点坐标:").split()) end_x, end_y = map(int, input("请输入终点坐标:").split()) start = Point(start_x, start_y) end = Point(end_x, end_y) path = a_star(start, end, obstacles, rows, cols) if path is None: print("无法到达终点") else: print("线路长:", len(path)-1, end="") for i in range(len(path)): print("{},{}".format(path[i].x, path[i].y), end="") if i < len(path)-1: print("-->", end="") print() --相关问题--:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值