已知地图如下所示,小明家在坐标原点(0,0),学校坐标(x,y),已知某2个点(可能为家或学校)在修路,因而不能通过这两点,小明走路只能向上和向右走,求出从家到达学校共有几种走法。下图中,修路的两点以黑点标识。
输入格式:
首先输入测试组数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