题意:输入n个国家,每个国家一些点,用围墙(多边形)围起来,围墙内的范围都属于这个国家,现在要发射一些导弹,如果导弹落到国家内,那对应的国家就会停电,现在问停电的总面积。
分析:1,求凸包,Graham扫描先把围墙上的点求出来,凸包完成。
2,求国家的面积,把多边形分成多个三角形,叉积a*b*sin<a,b>就是三角形面积的两倍,然后相加求得多边形面积。
3,判断点是否在多边形内,用射线进行判断,从该点引出射线,判断和多边形边相交的情况,注意射线和多边形交于多边形的顶点情况。
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 111
#define EPS 1e-10
struct point
{
double x,y;
point(double x,double y):x(x),y(y){}
point(){}
bool operator< (const point &s)const
{
return (x-s.x<-EPS)||(abs(x-s.x)<EPS&&y<s.y);
}
double det(point a)
{
return x*a.y-y*a.x;
}
double dot(point a)
{
return x*a.x+y*a.y;
}
point operator-(point a)
{
return point(x-a.x,y-a.y);
}
point operator +(point a)
{
return point(x+a.x,y+a.y);
}
point operator *(double s)
{
return point(x*s,y*s);
}
};
point p[N],res[N][N];
double s[N];
int kingdom[N],destory[N]={0};
point dir[4] = {point(501,-501),point(-501,501),point(501,501),point(-501,-501)};
bool ispointin(point p,int n);
point intersection(point p1,point p2,point q1,point q2);
bool on_seg(point p1,point p2,point p3);
double area(int n);
int main()
{
int kingdom_num=0,n=0;
while(~scanf("%d",&kingdom[n])&&kingdom[n]!=-1)
{
for(int i=0;i<kingdom[n];i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
sort(p,p+kingdom[n]);
int k=0;
for(int i=0;i<kingdom[n];i++)//求下凸点
{
while(k>1&&(res[n][k-1]-res[n][k-2]).det(p[i]-res[n][k-2])<EPS)
k--;
res[n][k++]=p[i];
}
int t=k;
for(int i=kingdom[n]-2;i>=0;i--)//求上凸点
{
while(k>t&&(res[n][k-1]-res[n][k-2]).det(p[i]-res[n][k-2])<EPS)
k--;
res[n][k++]=p[i];
}
kingdom[n]=k;
s[n]=area(n);
kingdom_num++;
n++;
}
int x,y;
double ans=0;
while(~scanf("%d%d",&x,&y))
{
for(int i=0;i<kingdom_num;i++)
{
if(ispointin(point(x,y),i))
{
ans+=s[i];
}
}
}
printf("%.2f\n",ans);
return 0;
}
//求凸多边形面积
double area(int n)
{
double sum=0;
res[n][kingdom[n]]=res[n][0];
for(int i=0;i<kingdom[n];i++)
{
sum=sum+(res[n][i].det(res[n][i+1]));
}
return sum/2;
}
//判断点是否在线段上
bool on_seg(point p1,point p2,point p3)
{
return abs((p1-p3).det(p2-p3))<EPS&&(p1-p3).dot(p2-p3)<EPS;
}
//求两直线交点
point intersection(point p1,point p2,point q1,point q2)
{
return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
//判断点是否在多边形内
bool ispointin(point p,int n)
{
if(destory[n])
return 0;
for(int i=0;i<4;i++)
{
int k=0;
res[n][kingdom[n]-1]=res[n][0];
for(int j=0;j<kingdom[n]-1;j++){
if(on_seg(res[n][j],res[n][j+1],p))
return 1;
point intersect=intersection(p,dir[i],res[n][j],res[n][j+1]);
if(on_seg(res[n][j],res[n][j+1],intersect)&&on_seg(p,dir[i],intersect))
k++;
if(on_seg(p,dir[i],res[n][j]))
k--;
}
if(k%2==0)
return 0;
}
destory[n]=1;
return 1;
}