zoj 3500 Electron Cloud(円欠式)
1666 ワード
【テーマの大意】:2つの球心の座標と半径を与えて、ボールの交際を求めます
【解題の考え方】:円欠公式~~テンプレートテスト
【コード】:
【解題の考え方】:円欠公式~~テンプレートテスト
【コード】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const double pi = 3.14159265358979323846;
const double eps = 1e-10;
struct Point
{
double x,y,z;
}d[2];
double get_v(double R, double h)
{
return pi*R*h*h - 1/3.0*pi*h*h*h;
}
double ball(double r)
{
return 4.0/3.0 * pi * r*r*r;
}
double cal(double r1, double r2, double dis) {
return (r1 * r1 - r2 * r2 + dis * dis) / (2 * dis);
}
int main()
{
int n;
double r1, r2;
scanf("%d", &n);
while (n--)
{
scanf("%lf%lf%lf%lf", &d[0].x, &d[0].y, &d[0].z, &r1);
scanf("%lf%lf%lf%lf", &d[1].x, &d[1].y, &d[1].z, &r2);
double dis = sqrt((d[0].x-d[1].x)*(d[0].x-d[1].x) + (d[0].y-d[1].y)*(d[0].y-d[1].y)
+(d[0].z-d[1].z)*(d[0].z-d[1].z));
if (dis >= r1 + r2) printf("%.2f
", ball(r1) + ball(r2));
else
{
if (dis - (max(r1,r2)-min(r1,r2)) <= eps) printf("%.2f
", ball(max(r1,r2)));
else
{
double ans = ball(r1) + ball(r2);
double x1 = cal(r1, r2, dis);
double v1 = get_v(r1, r1-x1);
double v2 = get_v(r2, r2-dis+x1);
ans -= (v1 + v2);
printf("%.2f
", ans);
}
}
}
return 0;
}