ZOJ3720 Magnet Darts(点在多边形内)

第一道点在多边形内的判断题,一开始以为是凸的。其实题意很简单的啦,最后转化为判断一个点是否在一个多边形内。

如果只是简单的凸多边形的话,我们可以枚举每条边算下叉积就可以知道某个点是不是在范围内了。但对于更一般的多边形,要采用的方法可能就要复杂一些,其中一种是叫做射线法的东西,在该点上画一条射线,如果射线与多边形偶数次相交,则说明点在多边形外,否则在多边形内。实践中可以取水平的一条,至于怎么判断就要看下代码了,判断的过程中如何发现点已经在多边形上了则直接返回。

计算几何做的少,则是算是补充了一个盲区吧。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
#define mod 1000000007
#define maxn 1000000
#define eps 1e-6
using namespace std;

struct Point
{
	int x, y;
	Point(int xi, int yi) :x(xi), y(yi){}
	Point(){}
	int dot(const Point &b){
		return x*b.x + y*b.y;
	}
	int det(const Point &b){
		return x*b.y - y*b.x;
	}
	Point operator - (const Point &b){
		return Point(x - b.x, y - b.y);
	}
}p[25];

int dcmp(double x){
	return (x > eps) - (x < -eps);
}

int n;
double A, B;
double lx, rx, ly, ry;

bool onLine(Point x, Point aa, Point bb)
{
	return (bb - aa).det(x-aa) == 0 && (bb - x).dot(aa - x) <= 0;
}

bool inside(Point x)
{
	int ret = 0;
	for (int i = 0; i < n; i++){
		if (onLine(x, p[i], p[(i + 1) % n])) return true;
		int k = (p[(i + 1) % n] - p[i]).det(x - p[i]);
		int d1 = x.y - p[i].y;
		int d2 = x.y - p[(i + 1) % n].y;
		if (k > 0 && d1 >= 0 && d2 < 0) ret++;
		if (k < 0 && d2 >= 0 && d1 < 0) ret--;
	}
	return ret != 0;
}

int main()
{
	while (cin>>lx>>ly>>rx>>ry){
		scanf("%d%lf%lf", &n, &A, &B);
		for (int i = 0; i < n; i++){
			scanf("%d%d", &p[i].x, &p[i].y);
		}
		p[n].x = p[0].x; p[n].y = p[0].y;
		double ans = 0;
		int llx = ceil(lx), rrx = floor(rx);
		int lly = ceil(ly), rry = floor(ry);

		for (int i = llx; i <= rrx; i++){
			for (int j = lly; j <= rry; j++){
				if (inside(Point(i, j))){
					double h = min(i + 0.5, rx) - max(i - 0.5, lx);
					double w = min(j + 0.5, ry) - max(j - 0.5, ly);
					ans += (A*i + B*j)*h*w;
				}
			}
		}
		ans /= (double)(rx - lx)*(ry - ly);
		printf("%.3lf
", ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/chanme/p/3634396.html