UVALive 6092 - Catching Shade in Flatland(线段和圆交线段最大长度)

题目链接:
UVALive 6092 - Catching Shade in Flatland
题意:
n 个都在(±400,±400)的圆,有一条线段 (0,0)(0,500) 绕原点24小时旋转一圈,记录每一分钟和这些圆交线段的长度,求最大长度。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 210;
const double eps = 1e-8;
const double pi = acos(-1.0);

int sgn(double x)
{
    if(fabs(x) <= eps) return 0;
    else if(x > eps) return 1;
    else return -1; 
}

struct Point{
    double x, y;

    Point() {}
    Point(double _x, double _y) : x(_x), y(_y) {}
    bool operator == (const Point& rhs) const {
        return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0;
    }
    bool operator < (const Point& rhs) const {
        return sgn(x - rhs.x) == 0 ? sgn(y - rhs.y) < 0 : x < rhs.x;
    }
    Point operator - (const Point& rhs) const {
        return Point(x - rhs.x, y - rhs.y);
    }
    Point operator + (const Point&  rhs) const {
        return Point(x + rhs.x, y + rhs.y);
    }
    Point operator * (const double d) const {
        return Point(x * d, y * d);
    }
    Point operator / (const double d) const {
        return Point(x / d, y / d);
    }
    double dot(const Point& rhs) const { //点积
        return x * rhs.x + y * rhs.y;
    }
    double cross(const Point& rhs) const { //叉积
        return x * rhs.y - y * rhs.x;
    }
    double dis(const Point& rhs) const { //两点距离
        return hypot(x - rhs.x, y - rhs.y);
    }
    double len(){ //长度
        return hypot(x, y);
    }

};

struct Line{
    Point s, e;

    Line() {}
    Line(const Point& _s, const Point& _e) : s(_s), e(_e) {}
    bool operator == (const Line& rhs) const {
        return s == rhs.s && e == rhs.e;
    }
    double length() const { //线段长度
        return s.dis(e);
    }
    bool point_on_seg(const Point& rhs) const { //点在线段上的判断
        return sgn((rhs - s).cross(e - s)) == 0 && sgn((rhs - s).dot(rhs - e)) <= 0;
    }
    double point_to_line_dis(const Point& rhs) const{ //点到直线的距离
        return fabs((rhs - s).cross(e - s)) / length();
    }
    double point_to_seg_dis(const Point& rhs) const { //点到线段的距离
        if(sgn((rhs - s).dot(e - s)) < 0 || sgn((rhs - e).dot(s - e)) < 0){
            return min(rhs.dis(s), rhs.dis(e));
        }else return point_to_line_dis(rhs);
    }
};

struct Circle{
    double x, y, r;

    Circle() {}
    Circle(double _x, double _y, double _r) : x(_x), y(_y), r(_r) {}
}circle[MAX_N];

Line ray;
Point inter1, inter2, ori = Point(0.0, 0.0), sun;

inline double check()
{
    double len = inter1.dis(inter2);
    if(ray.point_on_seg(inter1) && ray.point_on_seg(inter2)) return len;
    else if(ray.point_on_seg(inter1)) return ori.dis(inter1);
    else if(ray.point_on_seg(inter2)) return ori.dis(inter2);
    else return 0.0;
}

int main()
{
    int n;
    double R = 500.0, angle = pi / 720.0;
    //printf("angle * 1440 = %.10lf 2 * pi = %.10lf\n", angle * 1440, 2 * pi);
    while(~scanf("%d", &n) && n) {
        for(int i = 0; i < n; ++i) {
            scanf("%lf%lf%lf", &circle[i].x, &circle[i].y, &circle[i].r);
        }
        double ans = 0.0, tmp;
        for(int i = 0; i < 1440; ++i) {
            double x0 = R * sin(angle * i), y0 = R * cos(angle * i);
            sun = Point(x0, y0);
            ray = Line(ori, sun);
            tmp = 0.0;
            if(sgn(x0) == 0) continue;
            for(int j = 0; j < n; ++j) {
                double x = circle[j].x, y = circle[j].y, r = circle[j].r;
                Point center = Point(x, y);
                if(sgn(ray.point_to_line_dis(center) - r) >= 0) continue;
                double a = R * R, b = 2 * x * x0 * x0 + 2 * x0 * y0 * y, c = x0 * x0 * (x * x + y * y - r * r);
                double tt = sqrt(b * b - 4 * a * c);
                double x1 = (b - tt) / 2.0 / a, x2 = (b + tt) / 2.0 / a;
                inter1 = Point(x1, x1 * y0 / x0), inter2 = Point(x2, x2 * y0 / x0);
                tmp += check();
            }
            //if(tmp > ans) printf("i = %d i * angel = %.3lf tmp = %.3lf ans = %.3lf\n", i, angle * i, tmp, ans);
            ans = max(ans, tmp);
        }
        //右半横轴上
        sun = Point(500.0, 0.0);
        tmp = 0.0;
        for(int i = 0; i < n; ++i) {
            double x = circle[i].x, y = circle[i].y, r = circle[i].r;
            if(sgn(r - fabs(y)) <= 0) continue;
            double tt = sqrt(r * r - y * y);
            double x1 = x - tt, x2 = x + tt;
            inter1 = Point(x1, 0.0), inter2 = Point(x2, 0.0);
            tmp += check();
        }
        //if(tmp > ans) printf("tmp = %.3lf ans = %.3lf\n", tmp, ans);
        ans = max(ans, tmp);
        //左半横轴
        sun = Point(-500.0, 0.0);
        tmp = 0.0;
        for(int i = 0; i < n; ++i) {
            double x = circle[i].x, y = circle[i].y, r = circle[i].r;
            if(sgn(r - fabs(y)) <= 0) continue;
            double tt = sqrt(r * r - y * y);
            double x1 = x - tt, x2 = x + tt;
            inter1 = Point(x1, 0.0), inter2 = Point(x2, 0.0);
            tmp += check();
        }
        //if(tmp > ans) printf("tmp = %.3lf ans = %.3lf\n", tmp, ans);
        ans = max(ans, tmp);
        printf("%.3lf\n", ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值