python:三体问题

题目描述

沈学姐是一个科幻小说爱好者,最近她读了《三体》,喜欢数学的学姐对三体问题产生了兴趣。当然,学姐并不想去算某颗行星的轨道。

她把整个三体星系简化为一个平面,三颗恒星的球心投影成平面上的三点,每颗恒星都有一个半径为r的圆形引力场(r由恒星自身属性决定)。学姐想知道,三颗恒星的引力场总面积是多少。

输入

第一行为一个整数T,表示数据组数。

每组数据有三行输入:

每行有三个数x,y,r(保留两位小数),分别为该恒星中心坐标(x,y)和引力场半径r。

(|x|<=5,|y|<=5,0<=r<=5)

输出

对于第i组数据,输出一行,形如“Case #i: ans”(不含引号)

其中,ans表示引力场总面积,保留整数部分(因为学姐不想太难)。

样例输入

2
0.00 0.00 1.00
0.00 2.00 1.00
2.00 0.00 1.00
0.00 0.00 5.00
1.00 1.00 2.22
2.00 0.00 1.00

样例输出

Case #1: 9
Case #2: 79

参考代码:

#encoding :utf-8
import math
"""
这是求两个圆相交部分面积的参考代码(c):https://blog.csdn.net/aaakkk_1996/article/details/81746858
        double ang1=acos((r1*r1+d*d-r2*r2)/(2*r1*d));
        double ang2=acos((r2*r2+d*d-r1*r1)/(2*r2*d));
        return ang1*r1*r1 + ang2*r2*r2 - r1*d*sin(ang1);
"""
def judge(list1,list2):         #judge函数用来判定两圆之间的关系
    d = ((list1[0]-list2[0])**2+(list1[1]-list2[1])**2)**0.5
    if d >= list1[2]+list2[2]:          #此时两个圆相切或者相离
        return 1
    elif abs(list1[2]-list2[2])<d  and d<list1[2]+list2[2]:    #相交但不包含
        return 0
    elif abs(list1[2]-list2[2])>=d:
        return -1						#其中一个圆包含另一个

#返回不相交时的面积
def noCoincideArea(list1,list2):
    area = math.pi*(list1[2]*list1[2]+list2[2]*list2[2])
    return round(area)

#返回相交时的面积
def coincideArea(list1,list2):
    d = math.sqrt((list1[0] - list2[0]) ** 2 + (list1[1] - list2[1]) ** 2)
    ang1 = math.acos(((list1[2]*list1[2]) + d**2 - (list2[2]*list2[2]))/(2*d*list1[2]))
    ang2 = math.acos(((list2[2]) ** 2 + d ** 2 - (list1[2]) ** 2) / (2 * d * list2[2]))
    theCoincide = ang1*list1[2]*list1[2]+ang2*list2[2]*list2[2]-list1[2]*d*math.sin(ang1)
    area = (math.pi*(list1[2]*list1[2]+list2[2]*list2[2]))-theCoincide
    return round(area)

#判断三个圆知否存在包含关系,存在则删除被包含的那个圆
def isInclude(List):
    includeList = []
    if judge(List[0],List[1]) == -1:
        if min(List[0][2],List[1][2]) == List[0][2]:
            includeList.append(0)
        else:
            includeList.append(1)     #表示圆0包含圆1
    if judge(List[0],List[2]) == -1:
        if min(List[0][2],List[2][2]) == List[0][2]:
            includeList.append(0)
        else:
            includeList.append(2)  #表示圆0包含圆2
    if judge(List[1],List[2]) == -1:
        if min(List[1][2],List[2][2]) == List[1][2]:
            includeList.append(1)
        else:
            includeList.append(2)      #表示圆1包含圆2
    #开始删除被包含的圆
    if includeList:
        includeList = list(set(includeList))
        for i in sorted(includeList,reverse=True):
            List.pop(i)

T = eval(input())       #表示共几组数据
sumList = []
for i in range(T):
    data = []
    sum = 0
    for j in range(3):      #输入三个点的坐标和半径
        data.append(list(map(float,input().split())))
    #判断三个圆之间是否存在包含关系
    tempData = data[:]
    isInclude(tempData)
    if len(tempData) == 1:
        sumList.append(round(math.pi*tempData[0][2]*tempData[0][2]))
    elif len(tempData) == 2:
        if judge(tempData[0], tempData[1]) == 1:
            sumList.append(noCoincideArea(tempData[0], tempData[1]))
        elif judge(tempData[0], tempData[1]) == 0:  # 则表示两个圆有相交
            sumList.append(coincideArea(tempData[0], tempData[1]))
    else:
#包含关系,仅在排除不存在包含关系之后
        for j in range(len(tempData)-1):
            for k in range(j+1,len(tempData)):
                if judge(data[i],data[k]) == 1:
                    sum+=noCoincideArea(data[i],data[k])
                elif judge(data[i],data[k]) == 0:           #则表示两个圆有相交
                    sum+=coincideArea(data[i],data[k])
        sumList.append(round(sum/2))



    print("Case #"+str(i+1)+": "+str(sumList[i]))

你可能感兴趣的:(python)