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]))
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
问题是指三个天之间相互作用的问题,可以用牛顿万有引力定律来描述。为了模拟三问题,我们需要定义每个天的质量、初始位置和速度,并使用数值积分方法来计算它们的运动轨迹。以下是一个使用 Python 模拟三问题的示例代码: ```python import numpy as np import matplotlib.pyplot as plt # 定义天质量、初始位置和速度 m1, m2, m3 = 1, 1, 1 G = 1 r1 = np.array([-0.5, 0, 0]) r2 = np.array([0.5, 0, 0]) r3 = np.array([0, 1, 0]) v1 = np.array([0.5, 0.5, 0]) v2 = np.array([-0.5, -0.5, 0]) v3 = np.array([0, 0, 0]) # 定义运动方程 def f(r): x1, y1, z1, x2, y2, z2, x3, y3, z3 = r r12 = np.sqrt((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2) r13 = np.sqrt((x1 - x3)**2 + (y1 - y3)**2 + (z1 - z3)**2) r23 = np.sqrt((x2 - x3)**2 + (y2 - y3)**2 + (z2 - z3)**2) ax1 = G * m2 * (x2 - x1) / r12**3 + G * m3 * (x3 - x1) / r13**3 ay1 = G * m2 * (y2 - y1) / r12**3 + G * m3 * (y3 - y1) / r13**3 az1 = G * m2 * (z2 - z1) / r12**3 + G * m3 * (z3 - z1) / r13**3 ax2 = G * m1 * (x1 - x2) / r12**3 + G * m3 * (x3 - x2) / r23**3 ay2 = G * m1 * (y1 - y2) / r12**3 + G * m3 * (y3 - y2) / r23**3 az2 = G * m1 * (z1 - z2) / r12**3 + G * m3 * (z3 - z2) / r23**3 ax3 = G * m1 * (x1 - x3) / r13**3 + G * m2 * (x2 - x3) / r23**3 ay3 = G * m1 * (y1 - y3) / r13**3 + G * m2 * (y2 - y3) / r23**3 az3 = G * m1 * (z1 - z3) / r13**3 + G * m2 * (z2 - z3) / r23**3 return np.array([v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], ax1, ay1, az1, ax2, ay2, az2, ax3, ay3, az3]) # 使用 Runge-Kutta 数值积分方法计算运动轨迹 r = np.array([r1[0], r1[1], r1[2], r2[0], r2[1], r2[2], r3[0], r3[1], r3[2], v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]]) dt = 0.01 t = np.arange(0, 100, dt) x1, y1, z1, x2, y2, z2, x3, y3, z3 = np.zeros((9, len(t))) for i in range(len(t)): x1[i], y1[i], z1[i], x2[i], y2[i], z2[i], x3[i], y3[i], z3[i], vx1, vy1, vz1, vx2, vy2, vz2, vx3, vy3, vz3 = r k1 = dt * f(r) k2 = dt * f(r + 0.5 * k1) k3 = dt * f(r + 0.5 * k2) k4 = dt * f(r + k3) r += (k1 + 2 * k2 + 2 * k3 + k4) / 6 # 绘制运动轨迹 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot(x1, y1, z1, label='Body 1') ax.plot(x2, y2, z2, label='Body 2') ax.plot(x3, y3, z3, label='Body 3') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.legend() plt.show() ``` 在上述代码中,我们使用了 Runge-Kutta 数值积分方法来计算天的运动轨迹。具来说,我们将运动方程表示为 $f(r)$,其中 $r$ 是一个包含位置和速度的向量,然后使用 Runge-Kutta 方法迭代计算 $r$ 的值。最后,我们使用 Matplotlib 库绘制了三个天的运动轨迹。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值