boj 35 Video Surveillance 半平面交求多边形的核

//============================================================================
// Name        : 35.cpp
// Author      : wly
// Version     :
// Copyright   : Your copyright notice
// Description : Video Surveillance
// Algorithm   : 求多边形的核
//				 计算几何,半平面交求多边形的核
//				 http://blog.csdn.net/accry/article/details/6070621
//				 半平面交找核思想:
//				 对多边形的每一条边,这条边所在的直线都可以将平面分成两块,求一条边划分的半平面与之前得出的多边形的交,
//				 得出的多边形再与下一条边的半平面求交,依次类推,最后得到的多边形就是原多边形的核
//============================================================================


#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
using namespace std;
const double MAX = 100000000;
const double pi = acos(-1.0);
const double eps = 1e-8;
int cCnt, curCnt, n;
//点结构
struct Point {
	double x, y;
	Point(double ix, double iy) :
		x(ix), y(iy) {
	}
	Point() {
	}
	void input() {
		scanf("%lf%lf", &x, &y);
	}
} points[110], p[110], q[110];
//将两点确定的直线量化
inline void getline(Point x, Point y, double &a, double &b, double &c) {
	a = y.y - x.y;
	b = x.x - y.x;
	c = y.x * x.y - x.x * y.y;
}

int sig(double k) {
	return (k < -eps) ? -1 : (k > eps);
}
//x点y点的连线与量化后的直线求交点
void interect(Point x, Point y, double a, double b, double c) {
	double u = fabs(a * x.x + b * x.y + c);
	double v = fabs(a * y.x + b * y.y + c);
	q[++curCnt].x = (x.x * v + y.x * u) / (u + v);
	q[curCnt].y = (x.y * v + y.y * u) / (u + v);
}

//利用半平面切割
void cut(double a, double b, double c) {
	curCnt = 0;
	int i;
	for (i = 1; i <= cCnt; i++) //遍历所有顶点是否能观察到该边
	{
		if (sig(a * p[i].x + b * p[i].y + c) >= 0)//因为线段是顺时针给出的,如果是逆时针就是<=0
		{
			q[++curCnt] = p[i]; //若是则存储
		} else {
			if (sig(a * p[i - 1].x + b * p[i - 1].y + c) > 0)//逆时针就是<0
				interect(p[i - 1], p[i], a, b, c);
			if (sig(a * p[i + 1].x + b * p[i + 1].y + c) > 0)//逆时针就是<0
				interect(p[i + 1], p[i], a, b, c);
		}
	}
	//最后的p数组存放半平面的点集合
	for (i = 1; i <= curCnt; i++)
		p[i] = q[i];
	p[curCnt + 1] = p[1], p[0] = p[curCnt];
	cCnt = curCnt;
}
//半平面交初始化
inline void initial() {
	for (int i = 1; i <= n; ++i)
		p[i] = points[i];
	points[n + 1] = points[1];
	p[n + 1] = p[1];
	p[0] = p[n];
	cCnt = n;
}
//输入
inline void init() {
	for (int i = 1; i <= n; i++)
		points[i].input();
}
//获得多边形的核,结果存在p数组中,如果没有结果,p数组长度为0
inline void solve() {
	initial();
	for (int i = 1; i <= n; ++i) {
		double a, b, c;
		getline(points[i], points[i + 1], a, b, c);
		cut(a, b, c);
	}
	//多边形核的面积
	/*double area = 0;
	for (int i = 1; i <= curCnt; ++i)
		area += p[i].x * p[i + 1].y - p[i + 1].x * p[i].y;
	area = fabs(area / 2.0);*/
}

int main() {
	int tc = 1;
	while (scanf("%d", &n), n) {
		init();
		solve();
		printf("Floor #%d\n", tc++);
		if (!cCnt)
			puts("Surveillance is impossible.");//这里如果有一个点,或者一条线段都可以,所以判断m是不是等于0就行了,不用判断面积
		else
			puts("Surveillance is possible.");
		printf("\n");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值