标签:log 一个 printf poi sort operator else algorithm ret
半平面交第一题 !
题意是给出一个多边形,问他是否存在内核,即“可以看到任何一个地方的区域”。
内核即半平面交,下面是离线求半平面交的\(nlogn\)算法
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100;
struct Point{
double x,y;
Point(double xx=0,double yy=0){
x=xx,y=yy;
}
}a[maxn],p[maxn];
struct Vector{
double x,y;
Vector(double xx=0,double yy=0){
x=xx,y=yy;
}
};
struct Line{
Point p;
Vector v;
double ang;
Line(Point a=Point(),Vector b=Vector()){
p=a,v=b;
ang=atan2(b.y,b.x);
}
}b[maxn],q[maxn];
int dcmp(double x){return fabs(x)<1e-9?0:(x>0?1:-1);}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
Point operator + (Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
Vector operator * (double p,Vector a){return Vector(a.x*p,a.y*p);}
Vector operator * (Vector a,double p){return Vector(a.x*p,a.y*p);}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}
bool operator < (Line a,Line b){return a.ang<b.ang;}
bool onleft(Line a,Point b){return dcmp(a.v*(b-a.p))>0;}
Point glt(Point a,Point b,Point c,Point d){
Vector v1=b-a,v2=d-c,v3=a-c;
return a+v2*v3/(v1*v2)*v1;
}
int n,l,r;
void bpm(){
sort(b+1,b+n+1);
l=r=1;
q[1]=b[1]; //先加入第一条
for(int i=2;i<=n;i++){
while(l<r&&!onleft(b[i],p[r-1])) r--;
while(l<r&&!onleft(b[i],p[l])) l++; //如果不在左边就弹出去
q[++r]=b[i];
if(dcmp(b[i].v*q[r-1].v)==0){
r--;
if(onleft(q[r],b[i].p)) //这个应该是如果两个重合,就先把b[i]加入
q[r]=b[i];
}
if(l<r)
p[r-1]=glt(q[r-1].p,q[r-1].p+q[r-1].v,q[r].p,q[r].p+q[r].v); //交点更新
}
while(l<r&&!onleft(q[l],p[r-1])) r--; //有可能最后加入的几条是不合法的,要弹出来
}
int main(){
// freopen("3130.in","r",stdin);
while(1){
scanf("%d",&n);
if(n==0) break;
for(int i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=1;i<n;i++)
b[i]=Line(a[i],a[i+1]-a[i]);
b[n]=Line(a[n],a[1]-a[n]);
bpm();
if(r-l<=1) printf("0\n");
else printf("1\n");
}
return 0;
}
POJ-3130 How I Mathematician Wonder What You Are!
标签:log 一个 printf poi sort operator else algorithm ret
原文地址:https://www.cnblogs.com/nianheng/p/10010139.html