BSOJ1850:POJ1474摄像头 计算几何 半平面交

1850 -- 【POJ1474】监控摄像头
Description
一个著名的仓库管理公司SERKOI 请你为其安装一套闭路监视系统,由于SERKOI 财力有限,每个房间只能安装一台摄像机,不过其镜头可以向任何方向转换。 请你写一个程序,对于给定的房间示意图,判断是否有可能在这个房间中的某一位置安置一台摄像机,使其能监视到房间的每一个角落。
Input
输入文件有多组数据。每一组的第一行是一个整数n(4<=n<=100),表示房间的示意图是一个n边形。接下来n行,按照顺时针给出这n个点的坐标。最后一组的第一行是0,表示结束。
Output
如果能找出安放摄像机的点则输出
Floor #1
Surveillance is possible.
否则输出:
Floor #1
Surveillance is impossible.
#后边的数字表示房间编号,按输入数据由小到大编号,第一个房间编号为1。每一组数据完后输出一个空行。
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.


用给出的多边形来切一个极大的矩形,若是有剩下的块/点,说明可以监控到。

为什么呢?

我们说,要能观测到一条边,这个点一定在这条边的上方,比如:


中间的黄黄的阴影部分是合法的,其他的:

Block1----在E2下方,无法观测全部

Block2----在E1下方,无法观测全部


其实就是,当点连接边两点的两条边叉积之积>0,这个点在这条边的上方,

能观察到所有边的点一定能够观察到整个多边形区域。

其实再看,这个合法的块/点,就是拿这个多边形割这个平面得到的交。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct point
{
	double x,y;
}p[300005];
int n,m;
void pre()
{
	memset(p,0,sizeof(p));
}
double cross(point a,point b,point c)
{
	return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
point getnew(point a,point b,point c,point d)
{
	double l1=abs(cross(c,b,a));
	double l2=abs(cross(d,b,a));
	point ans;
	ans.x=(c.x*l2+d.x*l1)/(l1+l2);
	ans.y=(c.y*l2+d.y*l1)/(l1+l2);
	return ans;
}
void Cut(point last,point current)
{
	point store[35];
    int cnt=0;
    p[n+1]=p[1];
	for(int i=2;i<=n+1;i++)
	{
		double l=cross(p[i-1],current,last);
		double r=cross(p[i],current,last);
                //这里是顺时针给出的数据
		if(l>=0)
		{
			store[++cnt]=p[i-1];
			if(r<0)store[++cnt]=getnew(last,current,p[i],p[i-1]);
		}
		else if(r>0)store[++cnt]=getnew(last,current,p[i],p[i-1]);
	}
	for(int i=1;i<=cnt;i++)p[i]=store[i];
	n=cnt;
}
int main(){
	int test_case=0;
	while(1)
	{
	scanf("%d",&m);
	if(m==0)break;
	n=4;
	point last,current,first;
	pre();
	p[1]={-1e8,-1e8};
	p[2]={-1e8,1e8};
	p[3]={1e8,1e8};
	p[4]={1e8,-1e8};
        //极大矩形
	scanf("%lf%lf",&last.x,&last.y);
	first=last;
	for(int i=2;i<=m;i++)
	{
		scanf("%lf%lf",¤t.x,¤t.y);
		Cut(last,current);
		last=current;
	}
	Cut(last,first);
	test_case++;
	printf("Floor #%d\n",test_case);
	if(n>0)printf("Surveillance is possible.\n\n");
	else printf("Surveillance is impossible.\n\n");
   }
	
	return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值