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小时旋转一圈,记录每一分钟和这些圆交线段的长度,求最大长度。
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; }
相关文章推荐
- C#使用GDI绘制直线的方法
- Python判断直线和矩形是否相交的方法
- Python实现在matplotlib中两个坐标轴之间画一条直线光标的方法
- android 实现圆形imageView,Circle imageView.
- 通过HTML5 Canvas API绘制弧线和圆形的教程
- vtk画直线
- 初学算法 - 求凸包的Garham's Scan算法的C++实现
- 【Google Code Jam 2009 round2 problem D】Watering Plants (两圆交点求法详解)
- 计算几何模板
- 如何去绘制一个圆并且转为imageView格式
- IOS6 7下控件的圆角化,可做圆
- 计算几何小模板
- BZOJ2829信用卡凸包
- 绘制坐标图,折线图
- 三角函数在绘制圆中的使用
- 简单图形编程学习
- UVALive 4244 Party Party Party(HDU 2779 && Sicily 1663)
- UVALive 6741 The Sacrificial Firepits
- HDU 4922 Hello, Your Package! (计算几何+DP)(WA)
- poj 1514&zoj 1185 Metal Cutting(半平面交)