HDU
来源:互联网 发布:淘宝上的胆前级哪个好 编辑:程序博客网 时间:2024/06/05 11:50
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5130
题目大意:求多边形内的某个点P,使dis(P,B)<=dis(P,A),问P所构成的面积
解题思路:把上面的方程化开,可以得到一个圆的不等式,题目于是转化成既在圆内,又在多边形内的点所构成的面积,即两者相交的面积(为了使表达式简单点,我把每个坐标都进行了平移,使A的坐标为(0,0)),对于几何模板有不懂得可以参考博客:http://blog.csdn.net/Nightmare_ak/article/details/77944442
AC代码:
#include<cstdio>#include<cmath>#include<iostream>#include<algorithm>#include<iomanip>#include<vector>using namespace std;const int MAXN = 200000 + 5;const double PI = 3.1415926;const double EPS = 1e-10;double R;//反演圆半径int judgeZero(double a)//a>0为1,<0为-1,=0为0{ return (a > EPS) - (a < -EPS);}struct Point{ double _x, _y; Point(double x = 0.0, double y = 0.0) :_x(x), _y(y) {} Point(const Point& p) { _x = p._x, _y = p._y; } bool operator<(const Point& p)const { if (judgeZero(_x - p._x) != 0) return _x < p._x; return _y < p._y; } bool operator==(const Point& p)const { return judgeZero(_x - p._x) == 0 && judgeZero(_y - p._y) == 0; } void toMove(Point a, double rad, double d) { _x = a._x + cos(rad)*d; _y = a._y + sin(rad)*d; } Point operator+(Point a) { return Point(_x + a._x, _y + a._y); } Point operator-(Point a) { return Point(_x - a._x, _y - a._y); } friend Point operator*(double a, Point p) { return Point(a*p._x, a*p._y); } friend istream& operator >> (istream& in, Point& point) { in >> point._x >> point._y; return in; } friend ostream& operator<<(ostream& out, const Point& point) { out << fixed << setprecision(8) << point._x << ' ' << point._y; return out; }}crossp[MAXN];double getDis(Point a, Point b){ return sqrt((a._x - b._x)*(a._x - b._x) + (a._y - b._y)*(a._y - b._y));}typedef vector<Point> Polygon;struct Circle{ Point _o; double _r; Circle(double x = 0.0, double y = 0.0, double r = 0.0) :_o(x, y), _r(r) {} Circle(const Point& o, double r) :_o(o), _r(r) {} Circle getAnti(const Point& point) { Circle antic; double dis = getDis(point, _o); double tmp = R*R / (dis*dis - _r*_r); antic._r = tmp*_r; antic._o._x = point._x + tmp*(_o._x - point._x); antic._o._y = point._y + tmp*(_o._y - point._y); return antic; } friend istream& operator >> (istream& in, Circle& circle) { in >> circle._o >> circle._r; return in; } friend ostream& operator<<(ostream& out, const Circle& circle) { out << circle._o << ' ' << circle._r; return out; }};double getCross(Point p1, Point p2, Point p){ return (p1._x - p._x)*(p2._y - p._y) - (p2._x - p._x)*(p1._y - p._y);}bool onSegment(Point p, Point a, Point b)//点p与线段ab{ if (judgeZero(getCross(a, b, p)) != 0) return false; if (p._x<min(a._x, b._x) || p._x>max(a._x, b._x))//trick:垂直或平行坐标轴; return false; if (p._y<min(a._y, b._y) || p._y>max(a._y, b._y)) return false; return true;}bool segmentIntersect(Point a, Point b, Point c, Point d)//线段ab与线段cd{ if (onSegment(c, a, b) || onSegment(d, a, b) || onSegment(a, c, d) || onSegment(b, c, d)) return true; if (judgeZero(getCross(a, b, c)*getCross(a, b, d)) < 0 && judgeZero(getCross(c, d, a)*getCross(c, d, b)) < 0)//==0的特殊情况已经在前面排除 return true; return false;}bool onLine(Point p, Point a, Point b)//点p与直线ab{ return judgeZero(getCross(a, b, p)) == 0;}bool lineIntersect(Point a, Point b, Point c, Point d)//直线ab与直线cd{ if (judgeZero((a._x - b._x)*(c._y - d._y) - (c._x - d._x)*(a._y - b._y)) != 0) return true; if (onLine(a, c, d))//两直线重合 return true; return false;}bool segment_intersectLine(Point a, Point b, Point c, Point d)//线段ab与直线cd{ if (judgeZero(getCross(c, d, a)*getCross(c, d, b)) <= 0) return true; return false;}Point point_line_intersectLine(Point p1, Point p2, Point p3, Point p4)//求出交点,直线(线段)p1p2与直线(线段)p3p4{//t=lamta/(lamta+1),必须用t取代lamta,不然算lamta可能分母为0 double x1 = p1._x, y1 = p1._y; double x2 = p2._x, y2 = p2._y; double x3 = p3._x, y3 = p3._y; double x4 = p4._x, y4 = p4._y; double t = ((x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1)) / ((x2 - x1)*(y3 - y4) - (x3 - x4)*(y2 - y1)); return Point(x3 + t*(x4 - x3), y3 + t*(y4 - y3));}bool inPolygon(Point a, Polygon polygon)//点是否含于多边形{ Point b(-1e15 + a._x, a._y);//向左无穷远的线段 int count = 0; for (int i = 0;i < polygon.size();++i) { Point c = polygon[i], d = polygon[(i + 1) % polygon.size()]; if (onSegment(a, c, d)) //如果点在线段上,那么一定在多边形内 return true; if (judgeZero((a._x - b._x)*(c._y - d._y) - (c._x - d._x)*(a._y - b._y)) == 0) continue;//如果边与射线平行,trick1 if (!segmentIntersect(a, b, c, d)) continue;//如果边与射线没有交点 Point lower; if (c._y < d._y) lower = c; else lower = d; if (onSegment(lower, a, b)) //如果纵坐标小的点与射线有交点,trick2 continue; count++; } return count % 2 == 1;}bool segment_inPolygon(Point a, Point b, Polygon polygon)//线段是否含于多边形{ if (!inPolygon(a, polygon) || !inPolygon(b, polygon))//两个端点都不在多边形内 return false; int tot = 0; for (int i = 0;i < polygon.size();++i) { Point c = polygon[i], d = polygon[(i + 1) % polygon.size()]; if (onSegment(a, c, d))//以下只用记录一个交点,多的要么重复,要么一定在边上 crossp[tot++] = a; else if (onSegment(b, c, d)) crossp[tot++] = b; else if (onSegment(c, a, b)) crossp[tot++] = c; else if (onSegment(d, a, b)) crossp[tot++] = d; else if (segmentIntersect(a, b, c, d))//端点没有在线段上且相交 return false; } sort(crossp, crossp + tot);//按x,y排序 tot = unique(crossp, crossp + tot) - crossp; for (int i = 0;i < tot - 1;++i) { Point tmp = 0.5*(crossp[i] + crossp[i + 1]); if (!inPolygon(tmp, polygon))//中点不在多边形内 return false; } return true;}double lineDis_inPolygon(Point a, Point b, Polygon polygon)//求出直线在多边形内的长度{ int tot = 0; for (int i = 0;i < polygon.size();++i) { Point c = polygon[i], d = polygon[(i + 1) % polygon.size()]; if (onLine(c, a, b) && onLine(d, a, b))//如果边与直线重合,记录两个端点 { crossp[tot++] = c; crossp[tot++] = d; } else if (segment_intersectLine(c, d, a, b)) crossp[tot++] = point_line_intersectLine(a, b, c, d); } sort(crossp, crossp + tot); tot = unique(crossp, crossp + tot) - crossp; double ans = 0.0; for (int i = 0;i < tot - 1;++i) { Point tmp = 0.5*(crossp[i] + crossp[i + 1]); if (inPolygon(tmp, polygon)) ans += getDis(crossp[i], crossp[i + 1]); } return ans;}bool inCircle(Point p, Circle a)//点是否在圆内{ return judgeZero(getDis(p, a._o) - a._r) <= 0;}double dis_toSegment(Point c, Point a, Point b)//点到线段的最短距离{ Point d = a - b; double tmp = d._y;//得到与ab垂直的向量 d._y = d._x; d._x = -tmp; d.toMove(c, atan2(d._y, d._x), 10.0); Point intsect = point_line_intersectLine(a, b, c, d); if (onSegment(intsect, a, b)) return getDis(c, intsect); return min(getDis(c, a), getDis(c, b));}Polygon dividePolygon(Polygon p, Point a, Point b)//直线ab划分多边形{ int n = p.size(); Polygon newp; for (int i = 0;i < n;i++) { Point c = p[i], d = p[(i + 1) % n]; if (judgeZero(getCross(b, c, a)) > 0)//只记录向量ab左侧的多边形 newp.push_back(c); if (onLine(c, a, b))//防止重复记录点 newp.push_back(c); else if (onLine(d, a, b)) continue; else if (lineIntersect(a, b, c, d)) { Point tmp = point_line_intersectLine(a, b, c, d); if (onSegment(tmp, c, d)) newp.push_back(tmp); } } return newp;//要判断newp.size()>=3}double polygonArea(Polygon polygon)//多边形面积{ double ans = 0.0; for (int i = 1;i < polygon.size() - 1;i++) ans += getCross(polygon[i], polygon[i + 1], polygon[0]); return fabs(ans) / 2.0;}bool circle_inPolygon(Circle c, Polygon p)//圆含于多边形{ if (!inPolygon(c._o, p)) return false; for (int i = 0;i < p.size();i++) { Point a = p[i], b = p[(i + 1) % p.size()]; if (judgeZero(dis_toSegment(c._o, a, b) - c._r) < 0) return false; } return true;}bool polygon_inCircle(Circle c, Polygon p)//多边形含于圆{ for (int i = 0;i < p.size();i++) if (!inCircle(p[i], c)) return false; return true;}bool polygon_intersectCircle(Circle c, Polygon p)//圆含于多边形,多边形含于圆,圆和多边形相交,相切没算进去{ if (polygon_inCircle(c, p) || circle_inPolygon(c, p)) return true; for (int i = 0;i < p.size();i++) { Point a = p[i], b = p[(i + 1) % p.size()]; if (judgeZero(dis_toSegment(c._o, a, b) - c._r) < 0)//算相切要<=0 return true; } return false;}int point_line_intersectCircle(Circle c, Point a, Point b, Point p[])//线段ab与圆c的交点{ double A = (b._x - a._x)*(b._x - a._x) + (b._y - a._y)*(b._y - a._y); double B = 2.0 * ((b._x - a._x)*(a._x - c._o._x) + (b._y - a._y)*(a._y - c._o._y)); double C = (a._x - c._o._x)*(a._x - c._o._x) + (a._y - c._o._y)*(a._y - c._o._y) - c._r*c._r; double deta = B*B - 4.0 * A*C; if (judgeZero(deta) < 0) return 0; double t1 = (-B - sqrt(deta)) / (2.0 * A); double t2 = (-B + sqrt(deta)) / (2.0 * A); int tot = 0; if (judgeZero(t1) >= 0 && judgeZero(1 - t1) >= 0) p[tot++] = Point(a._x + t1*(b._x - a._x), a._y + t1*(b._y - a._y)); if (judgeZero(t2) >= 0 && judgeZero(1 - t2) >= 0) p[tot++] = Point(a._x + t2*(b._x - a._x), a._y + t2*(b._y - a._y)); if (tot == 2 && p[0] == p[1]) return 1; return tot;}double sectorArea(Circle c, Point p1, Point p2)//扇形面积op1p2{ Point op1 = p1 - c._o, op2 = p2 - c._o; double sita = atan2(op2._y, op2._x) - atan2(op1._y, op1._x); while (judgeZero(sita) <= 0) sita += 2 * PI; while (judgeZero(sita - 2 * PI) > 0) sita -= 2 * PI; sita = min(sita, 2 * PI - sita); return c._r*c._r*sita / 2.0;}double area_triangle_fromCircle(Circle c, Point a, Point b)//圆点,a,b构成的三角形与圆相交的面积{ bool flag1 = inCircle(a, c); bool flag2 = inCircle(b, c); if (flag1 && flag2)//两点在圆内 return fabs(getCross(a, b, c._o) / 2.0); Point p[2]; int tot = point_line_intersectCircle(c, a, b, p); if (flag1) return fabs(getCross(a, p[0], c._o) / 2.0) + sectorArea(c, p[0], b); if (flag2) return fabs(getCross(b, p[0], c._o) / 2.0) + sectorArea(c, p[0], a); if (tot == 2) return sectorArea(c, p[0], a) + sectorArea(c, p[1], b) + fabs(getCross(p[0], p[1], c._o)) / 2; return sectorArea(c, a, b);}double area_polygon_intersectCircle(Circle c, Polygon p)//多边形和圆的相交面积{ double ans = 0.0; for (int i = 0;i < p.size();i++)//trick:只需每相邻的点与圆心相连求相交面积,有向面积可以相互抵消 { Point a, b; a = p[i], b = p[(i + 1) % p.size()]; int flag = judgeZero(getCross(a, b, c._o)); ans += flag*area_triangle_fromCircle(c, a, b); } return fabs(ans);}int main(){ int n, cas = 1; double k; while (scanf("%d%lf", &n, &k) == 2) { Polygon p; for (int i = 0;i < n;++i) { double x1, y1; scanf("%lf%lf", &x1, &y1); p.push_back(Point(x1, y1)); } Point A, B; cin >> A >> B; for (int i = 0;i < n;++i) p[i]._x -= A._x, p[i]._y -= A._y; B._x -= A._x, B._y -= A._y; A._x = 0, A._y = 0; double a = B._x / (1 - k*k); double b = B._y / (1 - k*k); double c = (-B._x*B._x - B._y*B._y) / (1 - k*k); Circle C(Point(a, b), sqrt(c + a*a + b*b)); printf("Case %d: %.10f\n", cas++, area_polygon_intersectCircle(C, p)); } return 0;}
阅读全文
0 0
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- hdu
- hdu
- hdu
- HDU
- 如何解除mac上不能安装不明开发者的软件
- java8,你应该了解的新特性(并行流优化篇)
- windows环境配置:同时安装Python2.7和Python3.6开发环境
- 如何使log4j生成json格式的log
- cron 表达式
- HDU
- Springboot系列:Springboot与Thymeleaf模板引擎整合基础教程(附源码)
- linux下memcached单实例/多实例
- Java多线程(十)之ReentrantReadWriteLock深入分析
- 一种AS3下对SOUND对象进行整体、快速采样的方法
- C# : 字符串分割数组
- MYSQL的事物隔离级别
- ARM的六大类指令集
- 基于51单片的蓝牙小车项目