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; }