您的位置:首页 > 其它

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

2016-07-02 09:23 323 查看
题目链接:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息