CSP认证 202009-4 星际旅行 Python 题解 思路清晰
本题找对数学关系就很容易求了,分三种情况:
- P1,P2的连线 与圆心的距离 >=r,即这条直线在园外,P1和P2的最短距离就是欧式距离P1P2的连线。
- P1,P2的连线 与圆心的距离 <r,此时还要先判断这条线段是否在园外,判断条件为角OP1P2或者角OP2P1是否为钝角或直角,如果在园外那么也很简单,P1和P2的最短距离就是欧式距离P1P2的连线。
- P1,P2的连线穿过园,那么它们之间的距离分三段计算,具体看代码。
import math
n,m= list(map(int,input().split()))
r=int(input())
P=[]
dis=[]
Ol=list(map(int,input().split()))
for i in range(m):
P.append(list(map(int,input().split())))
def Euclidean(l1,l2):
sum=0
for i in range(n):
sum+=(l1[i]-l2[i])*(l1[i]-l2[i])
return math.sqrt(sum)
for i in range(m):
dis.append(Euclidean(Ol,P[i]))
def distance(i,j):
a=Euclidean(P[i],P[j])
b=dis[i]
c=dis[j]
p=(a+b+c)/2
h=2*math.sqrt(p*(p-a)*(p-b)*(p-c))/a
A=(a*a+b*b-c*c)/(2*a*b)
B=(a*a+c*c-b*b)/(2*a*c)
if A<=0 or B <=0:
return a
elif h >= r:
return a
else:
eta1=math.acos(r/b)
eta2=math.acos(r/c)
eta=math.acos((b*b+ c*c - a*a)/(2*b*c))
eta3=eta-eta1-eta2
arc=eta3 * r
len1=math.sqrt(b*b-r*r)
len2=math.sqrt(c*c-r*r)
return arc + len1 +len2
D=[[0]* m for _ in range(m)]
for i in range(m-1):
for j in range(i+1,m):
D[j][i] = D[i][j]=distance(i,j)
for i in range(m):
print((sum(D[i]))) #14位小数
此题用python是60分,运行超时,用C++可能会得更多的分数。
最后,其实发现ccf csp 认证的第四个题也不是很难,不是那种一点都做不出来的题目,只要认真看,认真思考,虽然不说满分,但是拿个一点分也不是不行的,加油!