POJ 1474 Video Surveillance 半平面交求多边形是否有核

裸的半平面交求多边形是否有核.

多边形的核: 在多边形核上的点可以看到多边形的所有顶点,凸多边形的核显然就是多边形本身.

多边形的核是一个凸包,对多边形的所有边都做向着多边形的半平面交在判断一下是否构成凸包就可以了

一样的题目还有POJ3335


Video Surveillance

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 3438   Accepted: 1523

Description

A friend of yours has taken the job of security officer at the Star-Buy Company, a famous depart- ment store. One of his tasks is to install a video surveillance system to guarantee the security of the customers (and the security of the merchandise of course)
on all of the store‘s countless floors. As the company has only a limited budget, there will be only one camera on every floor. But these cameras may turn around to look in every direction.

The first problem is to choose where to install the camera for every floor. The only requirement is that every part of the room must be visible from there. In the following figure the left floor can be completely surveyed from the position indicated by a dot,
while for the right floor, there is no such position, the given position failing to see the lower left part of the floor.

Before trying to install the cameras, your friend first wants to know whether there is indeed a suitable position for them. He therefore asks you to write a program that, given a ground plan, de- termines whether there is a position from which the whole floor
is visible. All floor ground plans form rectangular polygons, whose edges do not intersect each other and touch each other only at the corners.

Input

The input contains several floor descriptions. Every description starts with the number n of vertices that bound the floor (4 <= n <= 100). The next n lines contain two integers each, the x and y coordinates for the n vertices, given in clockwise order. All
vertices will be distinct and at corners of the polygon. Thus the edges alternate between horizontal and vertical.

A zero value for n indicates the end of the input.

Output

For every test case first output a line with the number of the floor, as shown in the sample output. Then print a line stating "Surveillance is possible." if there exists a position from which the entire floor can be observed, or print "Surveillance is impossible."
if there is no such position.

Print a blank line after each test case.

Sample Input

4
0 0
0 1
1 1
1 0
8
0 0
0 2
1 2
1 1
2 1
2 2
3 2
3 0
0

Sample Output

Floor #1
Surveillance is possible.

Floor #2
Surveillance is impossible.

Source

Southwestern European Regional Contest 1997

/* ***********************************************
Author        :CKboss
Created Time  :2015年04月09日 星期四 19时43分00秒
File Name     :POJ1474.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

#define mp make_pair
#define pb push_back

const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = 1e20;
const int maxp = 111;

int dcmp(double d) { if(fabs(d)<eps) return 0; return (d<0)?-1:1; }
inline double sqr(double x) { return x*x; }

struct point
{
	double x,y;
	point(double _x=0,double _y=0):x(_x),y(_y){}
	void input() { scanf("%lf%lf",&x,&y); }
	void output() { printf("%.2lf %.2lf\n",x,y); }
	bool operator==(point a) const { return dcmp(a.x-x)==0&&dcmp(a.y-y)==0; }
	bool operator<(point a) const { return dcmp(a.x-x)==0?dcmp(y-a.y)<0:x<a.x; }
	double len() { return hypot(x,y); }
	double len2() { return x*x+y*y; }
	double distance(point p) { return hypot(x-p.x,y-p.y); }
	point add(point p) { return point(x+p.x,y+p.y); }
	point sub(point p) { return point(x-p.x,y-p.y); }
	point mul(double b) { return point(x*b,y*b); }
	point div(double b) { return point(x/b,y/b); }
	double dot(point p) { return x*p.x+y*p.y; }
	double det(point p) { return x*p.y-y*p.x; }
	double rad(point a,point b)
	{
		point p=*this;
		return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
	}
};

struct line
{
	point a,b;
	line(){}
	line(point _a,point _b) { a=_a; b=_b; }
	bool operator==(const line v) const { return (a==v.a)&&(b==v.b); }
	bool parallel(line v) { return dcmp(b.sub(a).det(v.b.sub(v.a)))==0; }
	point crosspoint(line v)
	{
		double a1=v.b.sub(v.a).det(a.sub(v.a));
		double a2=v.b.sub(v.a).det(b.sub(v.a));
		return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
	}
};

struct halfplane:public line
{
	double angle;
	halfplane(){}
	/// a-->b left
	halfplane(point _a,point _b){ a=_a; b=_b;}
	halfplane(line v) { a=v.a; b=v.b; }
	void calcangle() { angle=atan2(b.y-a.y,b.x-a.x); }
	bool operator<(const halfplane &b) const { return angle<b.angle; }
};

struct halfplanes
{
	int n;
	halfplane hp[maxp];
	point p[maxp];
	int que[maxp];
	int st,ed;
	void push(halfplane tmp)
	{
		hp[n++]=tmp;
	}
	void unique()
	{
		int m=1,i;
		for(i=1;i<n;i++)
		{
			if(dcmp(hp[i].angle-hp[i-1].angle)) hp[m++]=hp[i];
			else if(dcmp(hp[m-1].b.sub(hp[m-1].a).det(hp[i].a.sub(hp[m-1].a))>0))
				hp[m-1]=hp[i];
		}
		n=m;
	}
	bool halfplaneinsert()
	{
		int i;
		for(int i=0;i<n;i++) hp[i].calcangle();
		sort(hp,hp+n);
		unique();
		que[st=0]=0; que[ed=1]=1;
		p[1]=hp[0].crosspoint(hp[1]);
		for(i=2;i<n;i++)
		{
			while(st<ed&&dcmp((hp[i].b.sub(hp[i].a).det(p[ed].sub(hp[i].a))))<0) ed--;
			while(st<ed&&dcmp((hp[i].b.sub(hp[i].a).det(p[st+1].sub(hp[i].a))))<0) st++;
			que[++ed]=i;
			if(hp[i].parallel(hp[que[ed-1]])) return false;
			p[ed]=hp[i].crosspoint(hp[que[ed-1]]);
		}
		while(st<ed&&dcmp((hp[st].b.sub(hp[que[st]].a).det(p[ed].sub(hp[que[st]].a))))<0) ed--;
		while(st<ed&&dcmp((hp[que[ed]].b.sub(hp[que[ed]].a).det(p[st+1].sub(hp[que[ed]].a))))<0) st++;
		if(st+1>=ed) return false;
		return true;
	}
};

int n;

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	int cas=1;
	while(scanf("%d",&n)&&n)
	{
		vector<point> vp;
		for(int i=0;i<n;i++)
		{
			point tp; tp.input(); vp.pb(tp);
		}
		halfplanes hfs; hfs.n=0;
		for(int i=0;i<n;i++)
		{
			//// p[i] <--- p[i+1]
			hfs.push(halfplane(vp[(i+1)%n],vp[i]));
		}
		printf("Floor #%d\n",cas++);
		bool isok=hfs.halfplaneinsert();
		if(isok==true) puts("Surveillance is possible.");
		else puts("Surveillance is impossible.");
		putchar(10);
	}

    return 0;
}
时间: 2024-10-06 00:38:41

POJ 1474 Video Surveillance 半平面交求多边形是否有核的相关文章

POJ 1474 Video Surveillance 半平面交求多边形内核存在性

题目大意:一个楼有很多层,每一层是一个多多边形,问每一层是否有点能够看到这一层的全貌. 思路:半平面交解多边形内核存在性,裸题.题中怎么没写数据范围?..让我还re几次.. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 3010 #define EPS 1e-8 #de

POJ 3335 Rotating Scoreboard 半平面交求多边形内核

题目大意:多边形求内核模板题 思路:半平面交,我用的是O(nlogn)的半平面交,但是有一个问题,就是当多边形内核是一个点的时候,半平面交所得到的答案是空集合,但是输出应该是yes,实在没有什么好的解决方法,最后只能把所有直线向右移动,然后在求内核.但是这样做eps的不同取值有的时候能A有的时候不能A.有没有什么好的解决方法啊!!!求解答啊!!! CODE: #include <cmath> #include <cstdio> #include <cstring> #i

POJ 3335 半平面交求多边形的核

Rotating Scoreboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4899   Accepted: 1946 Description This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spectators are seated along the ed

POJ 1279 Art Gallery 半平面交求多边形核

第一道半平面交,只会写N^2. 将每条边化作一个不等式,ax+by+c>0,所以要固定顺序,方便求解. 半平面交其实就是对一系列的不等式组进行求解可行解. 如果某点在直线右侧,说明那个点在区域内,否则出现在左边,就可能会有交点,将交点求出加入. //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #inc

poj 1474 Video Surveillance (半平面交)

链接:http://poj.org/problem?id=1474 Video Surveillance Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3247   Accepted: 1440 Description A friend of yours has taken the job of security officer at the Star-Buy Company, a famous depart- ment

POJ 1279 Art Gallery 半平面交+求多边形核的面积

裸的:半平面交+求多边形核的面积 Art Gallery Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5735   Accepted: 2419 Description The art galleries of the new and very futuristic building of the Center for Balkan Cooperation have the form of polygons (not

POJ 3130 How I Mathematician Wonder What You Are! 半平面交求多边形内核是否存在

题目大意:定义一种多边形,叫做星形多边形.这种多边形就是有内核的多边形.给出一些多边形,问是否是星形多边形. 思路:利用半平面交求解.PS:我的第一个多边形内核的代码不对..一定要看这个,这个是我看了学长的代码之后才发现之前的代码的问题的,这个也不用微调,是准确值,总值千万不要去看前面的那篇!!!! 由于内核中的所有点到图形上所有点的连线之间不能有边阻挡,所以为了满足任意一条边,需要满足内核的点必须在这条边所在直线的左边,所以将所有组成多边形的边所在的直线进行半平面交即可.由于一个多边形的内核也

半平面交 求多边形内核问题

多边形的内核可以理解为: 在多边形找到一块区域,使这块区域中的任何一个点都能够和多边形上的任意一点相连而不受到多边形上其他边的阻挡 也可以抽象的理解为在这块区域中任意位置放一个旋转摄像头,这个摄像头可以监控多边形的整个区域 多边形内核是否存在可以利用半平面交的思想去求解 将多边形上的每一条边作为逆时针顺序的射线,在每一条线左侧的就是可行区域 譬如: 比如这个多边形 蓝色区域便是内核 这样利用半平面交的nlogn的算法就可以轻松判断 这里是三道这样类型的题目:poj 3335 , poj 1474

POJ 1474 Video Surveillance 半平面交

和POJ 3130,POJ 3335一样.求多边形的核 #include <iostream> #include <cstdio> #include <cmath> #define eps 1e-18 using namespace std; const int MAXN = 105; double a, b, c; int n, cnt; struct Point { double x, y; }point[MAXN], p[MAXN], tp[MAXN]; void