路线统计,网格图路径数

已知地图如下所示,小明家在坐标原点(0,0),学校坐标(x,y),已知某2个点(可能为家或学校)在修路,因而不能通过这两点,小明走路只能向上和向右走,求出从家到达学校共有几种走法。下图中,修路的两点以黑点标识。

1615.png

输入格式:

首先输入测试组数T,然后输入T组测试;对于每组测试,输入学校坐标(x,y),两个修路点坐标(x1, y1),(x2, y2)。其中,0<=x, y, x1, y1, x2, y2<=30。

输出格式:

对于每组测试,输出从家(0,0)到达学校(x,y)共有几种走法。

输入样例:

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

输出样例:

1
0
0

import math


def C(n: int, m: int):
    """计算组合数"""
    return math.factorial(n) // (math.factorial(m) * math.factorial(n - m))


# 函数名乱起的,没意义
def Poi(b1: list, b2: list, s: list):
    """计算包含障碍物的路径条数"""
    t = [int(math.fabs(i[1] - i[0])) for i in zip(b1, b2)]
    kb1 = [i[1] - i[0] for i in zip(b1, s)]
    kb2 = [i[1] - i[0] for i in zip(b2, s)]
    cc = [i[1] - i[0] for i in zip(b1, b2)]

    # 计算通过两障碍物的路径条数之和
    r = C(sum(b1), b1[0]) * C(sum(kb1), kb1[0]) + C(sum(b2), b2[0]) * C(sum(kb2), kb2[0])

    # 重复路径检查:(即路径:起点,障碍物1 ,障碍物2,终点)
    if cc[0] * cc[1] < 0:
        # 两障碍物间不可到达,未重复计算
        return r
    else:
        # 存在重复计算,去重
        r = r - C(sum(b1), b1[0]) * C(sum(t), t[0]) * C(sum(kb2), kb2[0])
    return r


def EX():
    start = [0, 0]
    # 写入格式:(终点)x y (障碍物1)x y (障碍物2)x y
    a = [int(i) for i in input().split()]
    s = a[:2]
    bs = [a[2:4], a[4:]]
    # 确保第一个障碍物更接近起点
    bs.sort(key=lambda x: sum(x))
    b1 = bs[0]
    b2 = bs[1]
    # 计算起点和终点间所有路径的数量(不考虑障碍物)
    total = C(sum(s), s[1])
    # 处理障碍物在起点或者终点的状况
    if b1 == start or b2 == start or b1 == s or b2 == s:
        return 0
    # 处理障碍物分别堵住起点的状况
    if (b1 == [1, 0] or b1 == [0, 1]) and (b2 == [1, 0] or b2 == [0, 1]):
        return 0
    # 处理起点即是终点的状况
    if s == start:
        return 1
    # 减去障碍物阻碍的路径条数
    return total - Poi(b1, b2, s)


if __name__ == '__main__':
    # 读入n组数据
    N = int(input())
    for _ in range(N):
        print(EX())

不想放说明了

参考和思路指导:

设m行n列的网格,求从左上角走到右下角的不同路线条数,只能向右走或向下走,每次走一步 - 灰信网(软件开发博客聚合) (freesion.com)https://www.freesion.com/article/1938863974/组合数计算:组合数_百度百科 (baidu.com)https://baike.baidu.com/item/%E7%BB%84%E5%90%88%E6%95%B0/2153250?fr=aladdin

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值