http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1081
有一些经常用的几何知识,留着备用!
#include"iostream"
#include"string"
#include"cstdio"
#include"algorithm"
#include"cmath"
#define E 1e-8
#define MAX 1e5
#define N 99
using namespace std;
struct Point /*定义点*/
{
double x, y;
};
struct Segment /*定义线段*/
{
Point a, b;
};
double min(double x, double y)
{
return x > y ? y : x;
}
double max(double x, double y)
{
return x > y ? x : y;
}
double xmult(Point p1, Point p2, Point p0) /*计算两向量的叉积*/
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
bool is_online(Point p, Segment s) /*判断p是否在线段s上*/
{
if(fabs(xmult(s.a, p, s.b)) <= E && min(s.a.x, s.b.x) <= p.x &&
p.x <= max(s.a.x, s.b.x) && min(s.a.y, s.b.y) <= p.y && p.y <= max(s.a.y, s.b.y))
return true;
return false;
}
bool is_segment_crossing(Segment u, Segment v) /*判断两线段是否相交*/
{
return((max(u.a.x, u.b.x) >= min(v.a.x, v.b.x)) &&
(max(v.a.x, v.b.x) >= min(u.a.x, u.b.x)) &&
(max(u.a.y, u.b.y) >= min(v.a.y, v.b.y)) &&
(max(v.a.y, v.b.y) >= min(u.a.y, u.b.y)) &&
(xmult(v.a, u.b, u.a) * xmult(u.b, v.b, u.a) >= 0) &&
(xmult(u.a, v.b, v.a) * xmult(v.b, u.b, v.a) >= 0));
}
bool is_in_area(Point p, Point s[], int len) /*判断点p是否在以边点顺序排列的点集s所围成的多边形内*/
{
Segment seg;
Segment pp;
int num = 0;
Point MM;/*定义无穷点*/
MM.y = p.y;
MM.x = MAX;
pp.a = p;
pp.b = MM; /*构造一条平行于x轴的以p为端点的右射线pp*/
for(int i = 0; i < len; i++)
{
seg.a = s[i];
seg.b = s[(i+1)%len];
if(is_online(p, seg)) /*点p在边上*/
return true;
if(fabs(seg.a.y - seg.b.y) < E) /*水平*/
continue;
if(is_online(seg.a, pp)) /*边的一端点在射线上*/
{
if(seg.a.y > seg.b.y)
num++;
}
else if(is_online(seg.b, pp))
{
if(seg.b.y > seg.a.y)
num++;
}
else if(is_segment_crossing(pp, seg))
num++;
}
//cout<<num<<"::"<<endl;
if(num % 2 == 1)
return true;
return false;
}
int main()
{
int n;
Point s[N];
int pId = 0;
while(true)
{
scanf("%d", &n);
if(n == 0)
break;
int t;
scanf("%d", &t);
for(int i = 0; i < n; i++)
{
scanf("%lf%lf", &s[i].x, &s[i].y);
}
if(pId > 0)
printf("\n");
printf("Problem %d:\n", pId + 1);
for(int i = 0; i < t; i++)
{
Point p;
cin >> p.x >> p.y;
if(is_in_area(p, s, n))
printf("Within\n");
else
printf("Outside\n");
}
pId++;
}
}