5.布线问题


title: 5.布线问题
date: 2023-05-02 14:54:30
categories:

  • 大学课程内容
  • 大二下
  • 算法分析基础

5.布线问题

苏科大的sb输入输出数据,题目描述的输入输出和答案数据全是乱的。

【问题描述】

印刷电路板将布线区域划分成n*m个方格,精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案。在布线时,电路只能沿直线或直角布线。为了避免线路相交,已经布了线的方格不允许其他线穿过。对给定的电路板,找出最短的布线路径。

【输入形式】

方阵的行数、列数、布线区域方阵(其中不能通过的地方输入1,能通过的地方输入0)、起点坐标、终点坐标

【输出形式】

线路长度以及线路包含的方格坐标

【样例输入】

6 6
0 0 1 0 0 0
0 0 1 1 0 0
0 0 0 0 1 0
0 0 0 1 1 0
1 0 0 0 1 0
1 1 1 0 0 0
1 2
4 3

【样例输出】

4

1,2 > 2,2 > 3,2 > 4,2 > 4,3

【样例说明】

第1行输入方阵的行数、列数

第2-7行输入方阵元素,不能通过的地方输入1,能通过的地方输入0

第8行输入起点坐标

第9行输入终点坐标

所有元素用空格分隔, 且坐标索引从1开始!!

思路

思路很简单,就是BFS求最短路,只不过需要输出路径,那就记录前一个节点,最后回溯回去就可以

代码

import queue

# 输入地图大小
n, m = map(int, input().split())

# 初始化地图
g = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
for i in range(n):
    g[i + 1] = [0]+[int(x) for x in input().split()]

# 输入起点和终点
start = tuple(map(int, input().split()))
end = tuple(map(int, input().split()))

# 初始化距离和状态数组,以及父节点数组
dist = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
st = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
father = [[(0, 0) for _ in range(m + 1)] for _ in range(n + 1)]

# BFS 队列初始化,加入起点
q = queue.Queue()
q.put(start)
st[start[0]][start[1]] = 1

flag = False
while not q.empty() and not flag:
    # 弹出队首元素
    t = q.get()
    # 枚举四个方向
    for i in range(4):
        x = t[0] + [-1, 1, 0, 0][i]
        y = t[1] + [0, 0, -1, 1][i]
        # 判断是否越界或者障碍物已经被标记
        if x < 1 or x > n or y < 1 or y > m:
            continue
        if g[x][y] == 0 and st[x][y] == 0:
            # 如果可以走,则加入队列,更新距离,标记状态,记录父节点
            q.put((x, y))
            dist[x][y] = dist[t[0]][t[1]] + 1
            st[x][y] = 1
            father[x][y] = (t[0], t[1])
            # 判断是否到达终点
            if (x, y) == end:
                flag = True
                break

# 输出最短路距离
print(dist[end[0]][end[1]])

# 再次 BFS,打印路径
path = [end]
x = end[0]
y = end[1]
while (x, y) != start:
    # 获取当前点的父节点
    x, y = father[x][y]
    path.append((x, y))

# 反转路径,并输出
path.reverse()
for i in range(len(path)):
    if i == len(path) - 1:
        print("{},{}".format(path[i][0], path[i][1]))
    else:
        print("{},{}".format(path[i][0], path[i][1]), end="-->")

其他三个测试数据如下:

由第一个数据看出

# 测试数据1
6 6
0 0 1 0 0 0
0 0 1 1 0 0
0 0 0 0 1 0
0 0 0 1 1 0
1 0 0 0 1 0
1 1 1 0 0 0
1 2
4 3
# 输出
4
1,2-->2,2-->3,2-->4,2-->4,3


# 测试数据2
6 6
1 1 1 1 0 0
0 0 0 0 1 0
0 0 0 1 1 0
1 0 0 0 0 0
1 1 1 0 0 0
3 1
3 6
# 输出
9
3,1-->4,1-->4,2-->5,2-->5,3-->5,4-->5,5-->5,6-->4,6-->3,6


# 测试数据3
4 4
0 1 0 0
0 1 0 1
0 0 0 0
0 0 1 1
1 1
1 4
# 输出
7
1,1-->2,1-->3,1-->3,2-->3,3-->2,3-->1,3-->1,4
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

重生之我是cxk

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

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

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

打赏作者

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

抵扣说明:

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

余额充值