hdu 2892 Area

http://acm.hdu.edu.cn/showproblem.php?pid=2892

解题思路:

求多边形与圆的相交的面积是多少。

以圆心为顶点,将多边形划分为n个三角形。

接下来就求出每个三角形与圆相交的面积。

因为三角形的一个点是圆心,所以三角形的另外两个点与圆的情况有以下几种:

(1)两点都在圆里,三角形与圆相交的面积=三角形的面积。

(2)一个点在圆外,一个点在圆里,三角形与圆相交的面积=小三角形的面积+扇形面积

(3)两点都在圆外,又分为几种情况:

  1、两点构成的线段与圆相交的点数0或1个时,三角形与圆相交的面积=扇形的面积

  2.两点构成的线段与圆相交的点数2个时,三角形与圆相交的面积=大扇形面积+小三角形面积-小扇形的面积

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<algorithm>
  5 using namespace std;
  6
  7 #define MAXN 100000+10
  8 #define PI acos(-1.0)
  9 #define EPS 0.00000001
 10
 11 int dcmp(double x){
 12     if(fabs(x) < EPS)
 13         return 0;
 14     return x < 0 ? -1 : 1;
 15 }
 16
 17 struct Point{
 18     double x, y;
 19     Point(double x = 0, double y = 0): x(x), y(y) {}
 20 };
 21
 22 struct Circle{
 23     Point c;
 24     double r;
 25     Circle(Point c = Point(0, 0), double r = 0): c(c), r(r) {}
 26 };
 27
 28 typedef Point Vector;
 29
 30 Vector operator + (Vector A, Vector B){
 31     return Vector(A.x + B.x, A.y + B.y);
 32 }
 33 Vector operator - (Point A, Point B){
 34     return Vector(A.x - B.x, A.y - B.y);
 35 }
 36 Vector operator * (Vector A, double p){
 37     return Vector(A.x * p, A.y * p);
 38 }
 39 Vector operator / (Vector A, double p){
 40     return Vector(A.x / p, A.y / p);
 41 }
 42
 43 double dot(Vector A, Vector B){
 44     return A.x * B.x + A.y * B.y;
 45 }
 46
 47 double length(Vector A){
 48     return sqrt(dot(A, A));
 49 }
 50
 51 double angle(Vector A, Vector B){
 52     return acos(dot(A, B) / length(A) / length(B));
 53 }
 54
 55 double cross(Vector A, Vector B){
 56     return A.x * B.y - A.y * B.x;
 57 }
 58
 59 Circle bomb;//炸弹爆炸的坐标及半径
 60 Point p[MAXN];//岛屿的点
 61 int n;//岛屿点数
 62
 63 double point_line_distance(Point P, Point A, Point B){//点到直线的距离
 64     Vector AP = P - A, AB = B - A;
 65     return fabs(cross(AP, AB) / length(AB));
 66 }
 67
 68 Point point_line_projection(Point P, Point A, Point B){//点在直线上的映射
 69     Vector v = B - A;
 70     return A + v * (dot(v, P - A) / dot(v, v));
 71 }
 72
 73 int circle_line_intersect(Circle C, Point A, Point B, vector<Point> &v){
 74     double dist = point_line_distance(C.c, A, B);
 75     int d = dcmp(dist - C.r);
 76     if(d > 0){
 77         return 0;
 78     }
 79     Point pro = point_line_projection(C.c, A, B);
 80     if(d == 0){
 81         v.push_back(pro);
 82         return 1;
 83     }
 84     double len = sqrt(C.r * C.r - dist * dist);//勾股定理
 85     Vector AB = B - A;
 86     Vector l = AB / length(AB) * len;
 87     v.push_back(pro + l);
 88     v.push_back(pro - l);
 89     return 2;
 90 }
 91
 92 bool point_on_segment(Point P, Point A, Point B){//判断点在线段上
 93     Vector PA = A - P, PB = B - P;
 94     return dcmp(cross(PA, PB)) == 0 && dcmp(dot(PA, PB)) <= 0;
 95 }
 96
 97 double circle_delta_intersect_area(Circle C, Point A, Point B){
 98     Vector CA = A - C.c, CB = B - C.c;
 99     double da = length(CA), db = length(CB);
100
101     da = dcmp(da - C.r), db = dcmp(db - C.r);
102
103     if(da <= 0 && db <= 0){//三角形在圆里面
104         return fabs(cross(CA, CB)) * 0.5;
105     }
106
107     vector<Point> v;
108     int num = circle_line_intersect(C, A, B, v);//圆和直线的关系
109     double carea = C.r * C.r * PI;
110     Point t;
111     if(da <= 0 && db > 0){//左边的点在圆里 右边的点在圆外
112         t = point_on_segment(v[0], A, B) ? v[0] : v[1];
113
114         double area = fabs(cross(CA, t - C.c)) * 0.5, an = angle(CB, t - C.c);
115         return area + carea * an / PI / 2;
116     }
117     if(da > 0 && db <= 0){//左边点在圆外 右边点在圆里
118         t = point_on_segment(v[0], A, B) ? v[0] : v[1];
119
120         double area = fabs(cross(CB, t - C.c)) * 0.5, an = angle(CA, t - C.c);
121         return area + carea * an / PI / 2;
122     }
123     //两个点都在圆外
124     if(num == 2){
125         double bigarea = carea * angle(CA, CB) / PI / 2,
126             smallarea = carea * angle(v[0] - C.c, v[1] - C.c) / PI / 2,
127             deltaarea = fabs(cross(v[0] - C.c, v[1] - C.c)) * 0.5;
128         return bigarea + deltaarea - smallarea;
129     }
130     return carea * angle(CA, CB) / PI / 2;//两点都在圆外 直线AB与圆交点1个或两个
131 }
132
133 double circle_polygon_intersect_area(){//源于多边形相交面积
134     p[n] = p[0];
135     double ans = 0;
136     for(int i = 0; i < n; i++ ){
137         double area = circle_delta_intersect_area( bomb, p[i], p[i + 1] );
138         if(cross(p[i] - bomb.c, p[i + 1] - bomb.c) < 0){
139             area = -area;
140         }
141         ans += area;
142     }
143     return ans > 0 ? ans : -ans;
144 }
145
146 void solve(){
147     scanf("%d", &n );
148     for(int i = 0; i < n; i++ ){
149         scanf("%lf%lf", &p[i].x, &p[i].y );
150     }
151     printf("%.2lf\n", circle_polygon_intersect_area() );
152 }
153
154 int main(){
155     //freopen("data.in", "r", stdin );
156     double x, y, h, x1, y1, r;
157     while(~scanf("%lf%lf%lf", &x, &y, &h )){
158         scanf("%lf%lf%lf", &x1, &y1, &r  );
159
160         double t = sqrt(0.2 * h);//h = 0.5 * G * t^2 重力加速度公式
161
162         bomb = Circle( Point(x1 * t + x, y1 * t + y), r );
163
164         solve();
165     }
166     return 0;
167 }

hdu 2892 Area

时间: 2025-01-10 16:13:39

hdu 2892 Area的相关文章

hdu 2892 多边形与园面积相交

area Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 623    Accepted Submission(s): 233 Problem Description 小白最近被空军特招为飞行员,参与一项实战演习.演习的内容是轰炸某个岛屿... 作为一名优秀的飞行员,任务是必须要完成的,当然,凭借小白出色的操作,顺利地将炸弹投到了岛上某

HDU 4946 Area of Mushroom(凸包)

如果一个人能统治无穷远处,那么他的速度一定是最大的.除了那几种很坑的数据,比如同一个点速度相同的两个人.永远都是不可能.所以你要处理出来所有速度最大的点,然后用他们构成一个凸包,你把端点的点求出来了,还得判断一下在边上的情况.然后顶点和在边上的点所构成的就是可以到达无穷远处的人. PS:抄了芳姐的模版..哈哈哈 Area of Mushroom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/

HDU 4946 Area of Mushroom 凸包 第八次多校

Problem Description Teacher Mai has a kingdom with the infinite area. He has n students guarding the kingdom. The i-th student stands at the position (xi,yi), and his walking speed is vi. If a point can be reached by a student, and the time this stud

HDU 4946 Area of Mushroom 共线凸包

题意是在二维平面上 给定n个人 每个人的坐标和移动速度v 若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点) 则这个点称作被x占有 若有人能占有无穷大的面积 则输出1 ,否则输出0 思路: 1.把所有点按速度排个序,然后把不是最大速度的点去掉 剩下的点才有可能是占有无穷大的面积 2.给速度最大的点做个凸包,则只有在凸包上的点才有可能占有无穷大 若一个位置有多个人,则这几个人都是不能占有无穷大的. 凸包上边里共线的点是要保留的,, 附赠一波数据 #include <cs

hdu 2528 Area

2014-07-30 http://acm.hdu.edu.cn/showproblem.php?pid=2528解题思路: 求多边形被一条直线分成两部分的面积分别是多少.因为题目给的直线一定能把多边形分成两部分,所以就不用考虑多边形是否与直线相交.直接求问题. 将多边形的每一条边与直线判断是否相交.若相交,就从这点开始计算面积,直到判断到下一个边与直线相交的点.这之间的面积求出来为area2. area1为多边形的总面积.多边形被直线分成的另外一部分面积 = area1 - area2 有一个

【凸包】HDU 4946 Area of Mushroom

注意: 1.重合的点 2.速度为0的点 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using

hdu 4946 Area of Mushroom

题意: 在二维平面上,给定n个人 每个人的坐标和移动速度v 若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点) 则这个点称作被x占有,若有人能占有无穷大的面积 则输出1 ,否则输出0 思路: 1.把所有点按速度排个序,然后把不是最大速度的点去掉 剩下的点才有可能是占有无穷大的面积 2.给速度最大的点做个凸包,则只有在凸包上的点才有可能占有无穷大 若一个位置有多个人,则这几个人都是不能占有无穷大的. 凸包上边里共线的点是要保留的. #易错点: 1.凸包边上要保留共线的点

HDU 4946 Area of Mushroom 求凸包边上的点

点击打开链接 Area of Mushroom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1257    Accepted Submission(s): 307 Problem Description Teacher Mai has a kingdom with the infinite area. He has n studen

HDU 4946 Area of Mushroom(凸包)

HDU 4946 Area of Mushroom(凸包) ACM 题目地址:HDU 4946 Area of Mushroom 题意: 给定n个人,每个人的坐标和移动速度v,若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点),则这个点称作被x占有,若有人能占有无穷大的面积 则输出1 ,否则输出0. 分析: 到最后只有速度最大的点才有可能获得无穷大的面积.所以只要考虑速度最大的点. 很明显,只有这些点的凸包边上的点才能获得无穷大的面积. 所以求凸包边上的点就行了. 有