poj1474 Video Surveillance

题意:求多边形的内核,即:在多边形内部找到某个点,使得从这个点能不受阻碍地看到多边形的所有位置.

只要能看到所有的边,就能看到所有的位置.那么如果我们能够在多边形的内部的点x看到某条边AB,这个点x一定在AB的”内侧”,如果按逆时针方向给出多边形的所有顶点并假设从A到B是逆时针行走,”内侧”就是指有向直线A->B的左侧,那么多边形的每条边对应了一个半平面,要想看见这条边必须保证x在这个半平面内.而且,只要对于每条边x都在这条边的左侧,那么x就是一个可行的点,能够看到整个多边形.

这个结论的必要性是显然的(如果x在某条边的右侧,那么一定看不到这条边)

充分性也可以证:假如存在某个点是x看不见的,那么从x向这个点连线,一定会穿过偶数条多边形的边(因为每穿过一条边就从多边形的内部走到外部或者从外部走到内部,而起点终点都在内部),那么这些边一定是有一半从边的左侧穿到右侧(即从内到外),一半从边的右侧穿到左侧(即从外到内).也就是说,如果存在一个x看不见的点,就一定存在一条多边形的边使得x在这条边的右侧,于是如果找不到一条多边形的边使得x在这条边的右侧,就不存在x看不见的点,于是这个结论具有充分性.

那么我们对n条边求一下半平面交,判段是否非空即可.注意这里结果是一个点或一个线段时也判作有解,我的方法是把多边形的每条边都向多边形外部沿法向量方向平移一点,这样点和线段就都变成了面积不为0的区域,避免了边界讨论.

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=205;
const double eps=1e-8;
int cmp(double x){return x<-eps?-1:x>eps;}
struct point{
  double x,y;point(){}
  point(double a,double b){x=a;y=b;}
  void read(){scanf("%lf%lf",&x,&y);}
}P[maxn],p[maxn];
point operator +(point a,point b){return point(a.x+b.x,a.y+b.y);}
point operator -(point a,point b){return point(a.x-b.x,a.y-b.y);}
double cross(point a,point b){return a.x*b.y-a.y*b.x;}
struct line{
  point s,d;double arg;
  bool operator <(const line &B)const{return cmp(arg-B.arg)==-1;}
  line(){}
  line(point a,point b){s=a;d=b;arg=atan2(d.y,d.x);}
  void output(){
    printf("(%f,%f)+(%f,%f)\n",s.x,s.y,d.x,d.y);
  }
}L[maxn],q[maxn];
int n;
bool onleft(line A,point B){
  return cmp(cross(A.d,B-A.s))>0;
}
point mult(double t,point A){
  return point(t*A.x,t*A.y);
}
point intersect(line A,line B){
  double t=cross(B.d,A.s-B.s)/cross(A.d,B.d);
  return A.s+mult(t,A.d);
}
point rot(point A,double arg){
  return point(A.x*cos(arg)-A.y*sin(arg),A.x*sin(arg)+A.y*cos(arg));
}
int HPI(){
  sort(L,L+n);
  int head,tail;head=tail=0;q[tail++]=L[0];
  for(int i=1;i<n;++i){
    while(head+1<tail&&!onleft(L[i],p[tail-2]))tail--;
    while(head+1<tail&&!onleft(L[i],p[head]))  head++;
    q[tail++]=L[i];
    if(head+1<tail&&cmp(cross(q[tail-1].d,q[tail-2].d))==0){
      tail--;
      if(onleft(q[tail-1],L[i].s))q[tail-1]=L[i];
    }
    if(head+1<tail)p[tail-2]=intersect(q[tail-1],q[tail-2]);
  }
  while(head+1<tail&&!onleft(q[head],p[tail-2]))tail--;
  //  q[head].output();q[head+1].output();
  if(tail-head<=2)return 0;
  else return 1;
}
point normal(point A){return point(-A.y,A.x);}
point operator *(const double &t,const point &A){return point(A.x*t,A.y*t);}
int main(){
  int tests=0;
  while(scanf("%d",&n),n!=0){
    for(int i=0;i<n;++i)P[i].read();P[n]=P[0];
    for(int i=0;i<n;++i)L[i]=line(P[i]-eps*normal(P[i]-P[i+1]),P[i]-P[i+1]);
    if(HPI())printf("Floor #%d\nSurveillance is possible.\n",++tests);
    else printf("Floor #%d\nSurveillance is impossible.\n",++tests);
    printf("\n");
  }
  return 0;
}

 

转载于:https://www.cnblogs.com/liu-runda/p/6439781.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值