uvalive 2572
来源:互联网 发布:数据透视图 总数 编辑:程序博客网 时间:2024/06/06 00:43
题意:把n个圆盘依次放到桌面上,按放的顺序给出每个圆盘的坐标和半径,问最后多少个圆盘可见。
题解:如果把所有圆盘放好,基本上看到的都是完整的圆盘或者一些圆弧,那么把每一个圆盘和其他圆盘的交点求出来,每两个相邻的交点之间的圆弧也就可以得到,然后把这个圆弧的中点P往内外各移动一个很小的距离,得到P’和P”,把包含这两个点的最顶部的圆盘视为可见。注意很小的距离的取值。
#include <cstdio>#include <vector>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const double eps = 5e-13;const double PI = acos(-1);struct Point { double x, y; Point(double x = 0, double y = 0): x(x), y(y) {}};struct Circle { Point c; double r; Circle() {} Circle(Point c, double r = 0): c(c), r(r) {} Point point(double a) { return Point(c.x + cos(a) * r, c.y + sin(a) * c.y); }};int n, flag[105];Circle cir[105];//重载运算符Point operator + (Point A, Point B) { return Point(A.x + B.x, A.y + B.y);}Point operator - (Point A, Point B) { return Point(A.x - B.x, A.y - B.y);}Point operator * (Point A, double p) { return Point(A.x * p, A.y * p);}Point operator / (Point A, double p) { return Point(A.x / p, A.y / p);}//计算点积的正负 负值夹角为钝角int dcmp(double x) { if (fabs(x) < eps) return 0; return x < 0 ? -1 : 1;}bool operator == (const Point& a, const Point& b) { return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;}bool operator < (const Point& a, const Point& b) { return a.x < b.x || (a.x == b.x && a.y < b.y);}//计算点积 正负和夹角有关 |a||b|cosCdouble Dot(Point A, Point B) { return A.x * B.x + A.y * B.y;}//计算叉积,也就是数量积 向量A和B组成的三角形的有向面积的两倍//叉积等于0 三角形成为线段double Cross(Point A, Point B) { return A.x * B.y - A.y * B.x;}//计算向量长度double Length(Point A) { return sqrt(Dot(A, A));}//向量A旋转rad弧度,rad负值为顺时针旋转Point Rotate(Point A, double rad) { return Point(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));}void GetCircleIntersection(Circle a, Circle b, vector<double>& v) { if (dcmp(Length(a.c - b.c)) == 0) return; if (dcmp(Length(a.c - b.c) - a.r - b.r) > 0) return; if (dcmp(fabs(a.r - b.r) - Length(a.c - b.c)) > 0) return; double ang = atan2(b.c.y - a.c.y, b.c.x - a.c.x); double ang1 = acos((a.r * a.r + Length(a.c - b.c) * Length(a.c - b.c) - b.r * b.r) / (2.0 * a.r * Length(a.c - b.c))); v.push_back(ang - ang1); v.push_back(ang + ang1);}int topmost(Point p) { for (int i = n - 1; i >= 0; i--) if (Length(cir[i].c - p) < cir[i].r) return i; return -1;}int main() { while (scanf("%d", &n) == 1 && n) { memset(flag, 0, sizeof(flag)); int cnt = 0; for (int i = 0; i < n; i++) scanf("%lf%lf%lf", &cir[i].c.x, &cir[i].c.y, &cir[i].r); for (int i = 0; i < n; i++) { vector<double> v; v.push_back(0); v.push_back(PI * 2); for (int j = 0; j < n; j++) GetCircleIntersection(cir[i], cir[j], v); sort(v.begin(), v.end()); for (int j = 0; j < v.size(); j++) { double mid = (v[j] + v[j + 1]) / 2.0; double r1 = cir[i].r + eps; int t = topmost(Point(cir[i].c.x + cos(mid) * r1, cir[i].c.y + sin(mid) * r1)); if (t >= 0) flag[t] = 1; double r2 = cir[i].r - eps; t = topmost(Point(cir[i].c.x + cos(mid) * r2, cir[i].c.y + sin(mid) * r2)); if (t >= 0) flag[t] = 1; } } int res = 0; for (int i = 0; i < n; i++) if (flag[i]) res++; printf("%d\n", res); } return 0;}
0 0
- uvalive 2572
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- 互联网四大入口
- win7访问Linux Samba的共享目录提示“登录失败:用户名或密码错误”解决方法
- [设计模式]工厂模式
- IOS NSString比较,截取,NSLog,NSRang,isEqualToString,stringWithFormat
- iOS开发使用代码创建一个Label控件
- uvalive 2572
- Struts2学习笔记(一)入门示例
- S3C2440 LCD framebuffer 显示图像
- 文件的属性
- 安卓快捷键
- armlink scatter file
- 【黑马程序员】简略解析 java Scanner中的 next() 方法和 nextLine() 方法
- 初学者很实用:Web.xml常用元素
- Linux如何查看进程、杀死进程、启动进程等常用命令