P3945 | 三体问题 (天体物理+计算几何)
最近终于把《三体Ⅰ·地球往事》和《三体Ⅱ·黑暗森林》看完了!
为了快点认识题目中的歌者文明,已经开始第三部了!
题目背景
@FirstLight0521 出题人在这里哦~
三体人所居住的星系由于三体运动的不确定性而导致三体星人生活动荡不安,善良的人类程序员(也就是你了!伟大的英雄!)决定帮助愚蠢得连程序都不会写的三体星人模拟天体的运动轨迹。这时,无聊的“歌者”文明决定戏弄一下你,于是给三体星系添加了一些新的星体。
题目描述
输入 \(N\) 个天体与他们在空间中的坐标 \((xi,yi,zi)\) 、初速度 \((vx,vy,vz)\) 与质量 \(Mi\) ,已知三体世界受到“歌者”影响时间的流动不是连续的(每 \(0.01\) 秒钟刷新一次),天体均视为质点,求 \(t\) 时刻所有天体的坐标。
本题 \(G\) 取 \((6.67408×10^{-11})\) ,在代码中可以写成:
#define G 6.67408e-11
当你的答案与标准答案的相对误差不超过 \(0.5%\) 的时候,你在本测试点得到AC。
也就是说,保留多少位小数你可以自行确定。
标准答案将会保留 \(12\) 位小数。本题开启 \(SPJ\) 判断你的答案是否正确。
输入格式
第一行输入天体数 \(N\) 与时刻 \(t\) ,接下来逐行输入以空格分隔的各天体坐标、质量与初速度(三个方向上的分速度)。
输出格式
\(N\) 行,每行为第 \(i\) 个天体在t时刻的坐标 \(xi,yi,zi\) ,空格隔开。
输入输出样例
输入 #1
3 100
0 10 0 10000000 0.006207480877613 0 0
8.660254037844 -5 0 10000000 -0.003103740438807 -0.00537583613352 0
-8.660254037844 -5 0 10000000 -0.003103740438807 0.00537583613352 0
输出 #1
0.620349511786 9.980741705470 0.000000000000
8.333401109655 -5.527609289167 0.000000000000
-8.953750621441 -4.453132416303 0.000000000000
输入 #2
3 100
0 10 0 10000000 0.06207480877613 0 0
8.760254037844 -5 0 10000000 -0.03103740438807 -0.0537583613352 0
-8.660254037844 -5 0 10000000 -0.03103740438807 0.0537583613352 0
输出 #2
6.204092324054 9.982347016794 0.000000000000
5.642963405596 -10.364100727695 0.000000000000
-11.747055729651 0.381753710901 0.000000000000
说明/提示
\(3 <= N <= 30\),\(0 <= T <= 100\)。初始坐标范围为 \([-100, 100]\) 。质量在 \(int64\) 范围内。
——————————————————————————————————————————
首先彻底理解题意比较重要,题目描述中有一句很关键的话:时间的流动不是连续的(每 \(0.01\) 秒钟刷新一次)
这就等于告诉我们了我们所研究的只是一个粗糙的三体模型,不需要考虑各数值在任意时刻的变化情况。
而只考虑每极短时间( \(0.01\) 秒)的变化,根据物理知识,变化量就是各行星的坐标、速度和加速度。
我们在某 \(0.01\) 秒开始之前首先计算所有行星间因为万有引力产生的加速度,
然后根据高中物理学的微元法,视每个 \(0.01\) 内都为匀速直线运动,依次更新行星速度和坐标。
为了方便计算,我们将所有的矢量正交分解,即可把在同方向上的影响直接相加。
公式推导过程如下:
万有引力公式:\(F=G\frac{M·m}{r^2}\),加速度 \(a=G\frac{M}{r^2}\)
接着通过下图的几何关系就可以算出加速度在某方向上的分量(三维也是同理)。

代码如下:
#include <bits/stdc++.h>
#define G 6.67408e-11
using namespace std;
int n;
double t,t0=0.01;
struct ball {
double m,x,y,z,vx,vy,vz,ax,ay,az;
void read() { scanf("%lf%lf%lf%lf%lf%lf%lf",&x,&y,&z,&m,&vx,&vy,&vz); }
void pri() { printf("%.12lf %.12lf %.12lf\n",x,y,z); }
}body[233];
inline void along(int num) {
body[num].ax=body[num].ay=body[num].az=0.0;
for (int i=1;i<=n;i++) {
double d2,px,py,pz;
if (i==num) continue;
px=body[i].x-body[num].x;
py=body[i].y-body[num].y;
pz=body[i].z-body[num].z;
d2=px*px+py*py+pz*pz;
//计算加速度的分量
body[num].ax+=G*body[i].m/(d2*sqrt(d2))*px;
body[num].ay+=G*body[i].m/(d2*sqrt(d2))*py;
body[num].az+=G*body[i].m/(d2*sqrt(d2))*pz;
}
}
int main() {
scanf("%d%lf",&n,&t);
for (int i=1;i<=n;i++) body[i].read();
for (double now=0.00;now<=t;now+=t0) {
//先全部更新计算完影响之后,再移动。
for (int i=1;i<=n;i++) along(i);
for (int i=1;i<=n;i++) {
body[i].vx+=body[i].ax*t0;
body[i].vy+=body[i].ay*t0;
body[i].vz+=body[i].az*t0;
body[i].x+=body[i].vx*t0;
body[i].y+=body[i].vy*t0;
body[i].z+=body[i].vz*t0;
}
}
for (int i=1;i<=n;i++) body[i].pri();
return 0;
}
P3945 | 三体问题 (天体物理+计算几何)的更多相关文章
- ACM/ICPC 之 计算几何入门-叉积-to left test(POJ2318-POJ2398)
POJ2318 本题需要运用to left test不断判断点处于哪个分区,并统计分区的点个数(保证点不在边界和界外),用来做叉积入门题很合适 //计算几何-叉积入门题 //Time:157Ms Me ...
- HDU 2202 计算几何
最大三角形 Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- ACM 计算几何中的精度问题(转)
http://www.cnblogs.com/acsmile/archive/2011/05/09/2040918.html 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模 ...
- hdu 2393:Higher Math(计算几何,水题)
Higher Math Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- sdut 2603:Rescue The Princess(第四届山东省省赛原题,计算几何,向量旋转 + 向量交点)
Rescue The Princess Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 Several days ago, a b ...
- [知识点]计算几何I——基础知识与多边形面积
// 此博文为迁移而来,写于2015年4月9日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vxaq.html 1.前言 ...
- POJ 1106 Transmitters(计算几何)
题目链接 切计算几何,感觉计算几何的算法还不熟.此题,枚举线段和圆点的直线,平分一个圆 #include <iostream> #include <cstring> #incl ...
- TYVJ计算几何
今天讲了计算几何,发几道水水的tyvj上的题解... 计算几何好难啊!@Mrs.General....怎么办.... 这几道题都是在省选之前做的,所以前面的Point运算啊,dcmp啊,什么什么的,基 ...
- 计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点
平面最近点对,即平面中距离最近的两点 分治算法: int SOLVE(int left,int right)//求解点集中区间[left,right]中的最近点对 { double ans; //an ...
随机推荐
- 深入了解 Java 中的异常处理 + 面试题
# 深入了解 Java 中的异常处理 + 面试题 在程序开发中,异常处理也是我们经常使用到的模块,只是平常很少去深究异常模块的一些知识点.比如,try-catch 处理要遵循的原则是什么,finall ...
- 如何获取 C# 类中发生数据变化的属性信息
一.前言 在平时的开发中,当用户修改数据时,一直没有很好的办法来记录具体修改了那些信息,只能暂时采用将类序列化成 json 字符串,然后全塞入到日志中的方式,此时如果我们想要知道用户具体改变了哪几个字 ...
- PuTTYTabManager汉化版
PuTTY Tab Manager(puttytm) V0.52 zh_CN 简体中文汉化版 功能 Putty是一款小巧好用免费的SSH客户端工具,但是不支持多标签管理,网上找了一些相关的putty多 ...
- ATL的GUI程序设计(3)
第三章 ATL的窗口类 CWindowImpl.CWindow.CWinTraits,ATL窗口类的奥秘尽在此三者之中.在本章里,李马将为你详细解说它们的使用方法.另外,本章的内容也可以算是本书的核心 ...
- QQ IP 地址查询相关
1.QQwry.dat格式分析和查询IP位置的PHP程序 以前的追捕数据库太大,而且很久没有更新了. 所以我想到利用QQwry.dat这个文件查询IP所在位置,QQwry.dat 在很多地方都能找到, ...
- 基于 H5与webGL 的低碳工业园区监控系统
前言 低碳工业园区的建设与推广是我国推进工业低碳转型的重要举措,低碳工业园区能源与碳排放管控平台是低碳工业园区建设的关键环节.如何对园区内的企业的能源量进行采集.计量.碳排放核算,如何对能源消耗和碳排 ...
- gRPC初识
RPC算是近些年比较火热的概念了,随着微服务架构的兴起,RPC的应用越来越广泛.本文介绍了RPC和gRPC的相关概念,并且通过详细的代码示例介绍了gRPC的基本使用. RPC是什么 在分布式计算,远程 ...
- Java并发读书笔记:Lock与ReentrantLock
Lock位于java.util.concurrent.locks包下,是一种线程同步机制,就像synchronized块一样.但是,Lock比synchronized块更灵活.更复杂. 话不多说,我们 ...
- 题解【[HNOI2010]弹飞绵羊】
\[ \texttt{Description} \] 有 \(n\) 个弹力装置排成一排,第 \(i\) 个弹力装置的弹力系数是 \(k_i\) ,绵羊到第 \(i\) 个装置时,会被弹到第 \(i+ ...
- oracle查询表空间的空间占用情况
,) percent_used from (select tablespace_name,sum(bytes) bytes from dba_data_files group by tablespac ...