题目:http://poj.org/problem?id=1264
一道凸包题,求导弹射中的凸包的面积之和。
View Code
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
typedef struct
{
double x, y;
}cpoint;
double sqr(double x) {return x*x;}
double dcmp(double x)
{
if(x < -eps) return -1; else return x > eps;
}
double cross(cpoint p0, cpoint p1, cpoint p2)
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
double dot(cpoint p0, cpoint p1, cpoint p2)
{
return (p1.x - p0.x) * (p2.x - p0.x) + (p1.y - p0.y) * (p2.y - p0.y);
}
double dis(cpoint p1, cpoint p2)
{
return sqrt(sqr(p1.x - p2.x) + sqr(p1.y - p2.y));
}
double dissqr(cpoint p1, cpoint p2)
{
return sqr(p1.x - p2.x) + sqr(p1.y - p2.y);
}
int PointEqual(const cpoint p1, const cpoint p2)
{
return dcmp(p1.x - p2.x) == 0 && dcmp(p1.y - p2.y) == 0;
}
int PointOnSegment(cpoint p0, cpoint p1, cpoint p2)
{
return dcmp(cross(p0, p1, p2)) == 0 && dcmp(dot(p0, p1, p2)) <= 0;
}
cpoint bp;
int PolarCmp(const cpoint &p1, const cpoint &p2)
{
int u = dcmp(cross(bp, p1, p2));
return u > 0 || (u == 0 && dcmp(dissqr(bp, p1)-dissqr(bp, p2)) < 0);
}
int PointInPolygon(cpoint cp, cpoint p[], int n)
{
int i, k, d1, d2, wn = 0;
double sum = 0;
p[n] = p[0];
for (int i = 0; i < n; i++)
{
if (PointOnSegment(cp, p[i], p[i+1])) return 2;
k = dcmp(cross(p[i], p[i+1], cp));
d1 = dcmp(p[i+0].y - cp.y);
d2 = dcmp(p[i+1].y - cp.y);
if (k > 0 && d1 <= 0 && d2 > 0) wn++;
if (k < 0 && d2 <= 0 && d1 > 0) wn--;
}
return wn != 0;
}
void graham(cpoint pin[], int n, cpoint ch[], int &m)
{
int i, j, k, u, v;
memcpy(ch, pin, n*sizeof(cpoint));
for (i = k = 0; i < n; i++)
{
u = dcmp(ch[i].x - ch[k].x);
v = dcmp(ch[i].y - ch[k].y);
if (v < 0 || (v == 0 && u < 0)) k = i;
}
bp = ch[k];
sort(ch, ch + n, PolarCmp);
n = unique(ch, ch + n, PointEqual) - ch;
if (n <= 1) {m = n; return ;}
if (dcmp(cross(ch[0], ch[1], ch[n-1])) == 0)
{
m = 2; ch[1] = ch[n-1]; return ;
}
ch[n++] = ch[0];
for (i = 1, j = 2; j < n; j++)
{
while (i > 0 && dcmp(cross(ch[i-1], ch[i], ch[j])) <= 0) i--;
ch[++i] = ch[j];
}
m = i;
}
double PolygononArea(cpoint p[], int n)
{
if (n < 3) return 0;
double s = p[0].y * (p[n-1].x - p[1].x);
for (int i = 1; i<n; i++)
{
s += p[i].y * (p[i-1].x - p[(i+1) % n].x);
}
return fabs(s / 2.0);
}
cpoint kingdom[22][105];
cpoint polygon_kingdom[22][105];
int m[22], v[22];
int main()
{
//freopen("D:/a.txt", "r", stdin);
int n, top=0;
memset(v, 0, sizeof(v));
while(scanf("%d", &n))
{
if (n == -1)
{
//printf("-------------n = -1-------\n");
cpoint missile;
while (scanf("%lf%lf", &missile.x, &missile.y)!=EOF)
{
for (int i=0; i<top; i++)
{
if (PointInPolygon(missile, polygon_kingdom[i], m[i]))
{
v[i] = 1;
}
}
//printf("%.2lf %.2lf\n", missile.x, missile.y);
}
double area = 0;
for (int i=0; i<top; i++)
{
if (v[i]) {area += PolygononArea(polygon_kingdom[i], m[i]);}
}
printf("%.2lf\n", area);
break;
}
for (int i=0; i<n; i++)
{
scanf("%lf%lf", &kingdom[top][i].x, &kingdom[top][i].y);
}
//printf("---------\n");
graham(kingdom[top], n, polygon_kingdom[top], m[top]);
top++;
}
return 0;
}