Art Gallery
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7508 | Accepted: 2996 |
Description
The art galleries of the new and very futuristic building of the Center for Balkan Cooperation have the form of polygons (not necessarily convex). When a big exhibition is organized, watching over all of the pictures is a big security concern. Your task is that for a given gallery to write a program which finds the surface of the area of the floor, from which each point on the walls of the gallery is visible. On the figure 1. a map of a gallery is given in some co-ordinate system. The area wanted is shaded on the figure 2.
![](https://i-blog.csdnimg.cn/blog_migrate/4f45f42ad50f7027d0a983b507c75fc6.jpeg)
Input
The number of tasks T that your program have to solve will be on the first row of the input file. Input data for each task start with an integer N, 5 <= N <= 1500. Each of the next N rows of the input will contain the co-ordinates of a vertex of the polygon ? two integers that fit in 16-bit integer type, separated by a single space. Following the row with the co-ordinates of the last vertex for the task comes the line with the number of vertices for the next test and so on.
Output
For each test you must write on one line the required surface - a number with exactly two digits after the decimal point (the number should be rounded to the second digit after the decimal point).
Sample Input
1 7 0 0 4 4 4 7 9 7 13 -1 8 -6 4 -4
Sample Output
80.00
Source
题意:求内核面积
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const double eps = 1e-8;
int sgn(double x)
{
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
return 1;
}
struct Point
{
double x, y;
Point(double xx = 0, double yy = 0) : x(xx), y(yy){} //这里一定要 赋初值为0,要不编译错误。。
Point operator - (const Point &b) const
{
return Point(x-b.x, y-b.y);
}
double operator ^ (const Point &b) const
{
return x*b.y-y*b.x;
}
double operator *(const Point &b) const
{
return x*b.x + y*b.y;
}
};
struct Line
{
Point s, e;
double k;
Line(){}
Line(Point ss, Point ee)
{
s = ss; e = ee;
k = atan2(e.y-s.y, e.x-s.x); //斜率
}
Point operator &(const Line &b) const
{
Point res = s;
double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x += (e.x-s.x)*t;
res.y += (e.y-s.y)*t;
return res;
}
};
int HPIcmp(Line a, Line b) //排序。。
{
if(fabs(a.k - b.k) > eps) return a.k < b.k;
return ((a.s-b.s)^(b.e-b.s)) < 0;
}
Line Q[1510];
void HPI(Line line[], int n, Point res[], int &resn) //半平面。。
{
int tot = n;
sort(line, line+n, HPIcmp);
tot = 1;
for(int i = 1; i < n; i++)
{
if(fabs(line[i].k - line[i-1].k) > eps) //防止有相同线段吧
line[tot++] = line[i];
}
int head = 0, tail = 1;
Q[0] = line[0];
Q[1] = line[1];
resn = 0;
for(int i = 2; i < tot; i++)
{
if(fabs((Q[tail].e-Q[tail].s) ^ (Q[tail-1].e-Q[tail-1].s)) < eps ||
fabs((Q[head].e-Q[head].s) ^ (Q[head+1].e-Q[head+1].s)) < eps)
return;
while(head < tail && (((Q[tail]&Q[tail-1])-line[i].s)^(line[i].e-line[i].s)) > eps)
tail--;
while(head < tail && (((Q[head]&Q[head+1])-line[i].s)^(line[i].e-line[i].s)) > eps)
head++;
Q[++tail] = line[i];
}
while(head < tail && (((Q[tail]&Q[tail-1])-Q[head].s)^(Q[head].e-Q[head].s)) > eps)
tail--;
while(head < tail && (((Q[head]&Q[head-1])-Q[tail].s)^(Q[tail].e-Q[tail].s)) > eps)
head++;
if(tail <= head+1) return;
for(int i = head; i < tail; i++)
res[resn++] = Q[i]&Q[i+1]; //这个数组里都是内核吧。。
if(head < tail-1)
res[resn++] = Q[head]&Q[tail];
}
double CalcArea(Point p[], int n) //求面积
{
double res = 0;
for(int i = 0; i < n; i++)
res += (p[i]^p[(i+1)%n])/2;
return res;
}
Point p[1510];
Line line[1510];
int main()
{
int t, ca = 0;
cin >> t;
while(t--)
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%lf%lf", &p[i].x, &p[i].y);
if(CalcArea(p, n) < 0)
reverse(p, p+n);
for(int i = 0; i < n; i++)
line[i] = Line(p[i], p[(i+1)%n]);
int resn;
HPI(line, n, p, resn);
printf("%.2f\n", CalcArea(p, resn)); //不知道为啥还是穿入的p,只是把n改成resn了
}
return 0;
}