HDU 4316 凸包 +半平面交

题意:给出多边形的顶点,然后在天花板有三个摄像头,找出三个摄像头的盲区。

思路:每一个摄像头 对应有一个盲区,然后把三个摄像头的盲区取交集 然后求面积就可以 这里用到了 凸包模版和半平面交模版

代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct Point{
    double x,y,z;
    Point(double x=0,double y=0,double z=0):x(x),y(y),z(z) {}
};
Point tmp[200];
const double eps=1e-8;
typedef Point  Vector;
Vector operator -(Point A,Point B){
    return Vector(A.x-B.x,A.y-B.y);
}
Vector operator +(Point A,Point B){
    return Vector(A.x+B.x,A.y+B.y);
}
Vector operator *(Vector A,double p){
    return Vector(A.x*p,A.y*p);
}
double Cross(Vector A,Vector B){
    return A.x*B.y-A.y*B.x;
}
int n,res[1200],top;
Point p[1200];
bool mult(Point sp,Point ep,Point op){
    return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);
}
bool cmp(Point a,Point b){
    if(a.y==b.y)return a.x<b.x;
    return a.y<b.y;
}
struct Line{
    Point P;
    Vector v;
    double ang;
    Line(){}
    Line(Point P,Vector v):P(P),v(v){
        ang=atan2(v.y,v.x);
    }
    bool operator <(const Line &L)const{
        return ang<L.ang;
    }
};
bool Onleft(Line L,Point pp){
    return Cross(L.v,pp-L.P)>0;
}
Point GetIntersection(Line a,Line b){
    Vector u=a.P-b.P;
    double t=Cross(b.v,u)/Cross(a.v,b.v);
   // cout<<t<<endl;
    return a.P+a.v*t;
}
void Graham(){
    int len;
    top=1;
    sort(p,p+n,cmp);
    if(n==0)return;res[0]=0;
    if(n==1)return;res[1]=1;
    if(n==2)return;res[2]=2;
    for(int i=2;i<n;i++){
        while(top&&mult(p[i],p[res[top]],p[res[top-1]]))top--;
        res[++top]=i;
    }
    len=top;
    res[++top]=n-2;
    for(int i=n-3;i>=0;i--){
        while(top!=len&&mult(p[i],p[res[top]],p[res[top-1]]))top--;
        res[++top]=i;
    }
}

int HalfplaneIntersection(Line* L,int n,Point *poly){
    sort(L,L+n);
    int ft,la;
    Point *pp=new Point[n];
    Line *q=new Line[n];
    q[ft=la=0]=L[0];
    for(int i=1;i<n;++i) {
        while (ft<la&&!Onleft(L[i],pp[la-1]))
            --la;
        while (ft<la&&!Onleft(L[i], pp[ft])) ++ft;
        q[++la]=L[i];
        if(fabs(Cross(q[la].v,q[la-1].v))<eps){
            la--;
            if (Onleft(q[la], L[i].P))
                q[la]=L[i];
            
        }
        if(ft<la){
            pp[la-1]=GetIntersection(q[la-1],q[la]);
           // cout<<pp[la-1].x<<" "<<pp[la-1].y<<endl;
        }
    }
    while (ft<la&&!Onleft(q[ft],pp[la-1])) --la;
    if (la-ft<=1)
        return 0;
    pp[la]=GetIntersection(q[la],q[ft]);
    int m=0;
    for (int i=ft; i<=la; ++i) {
        poly[m++]=pp[i];
    }
    return m;
}
int main()
{
    Point a[3];Line l[1000];
    while (cin>>n) {
        for (int i=0; i<n; ++i)
            cin>>tmp[i].x>>tmp[i].y>>tmp[i].z;
        for (int i=0; i<3; ++i)
            cin>>a[i].x>>a[i].y;
        int tol=0;
        for (int i=0; i<3; ++i) {
            for (int j=0; j<n; ++j) {
                p[j].x=-100.0*(tmp[j].x-a[i].x)/(tmp[j].z-100)+a[i].x;
                p[j].y=-100.0*(tmp[j].y-a[i].y)/(tmp[j].z-100)+a[i].y;
            }
            Graham();
            //  cout<<top<<endl;
            for (int j=0;j<top; ++j){
              //  cout<<p[j].x<<" "<<p[j].y<<endl;
                l[tol++]=Line(p[res[j]],p[res[(j+1)%top]]-p[res[j]]);
            }
          //  cout<<endl;
        }
        //  cout<<tol<<endl;
        int m=HalfplaneIntersection(l, tol, tmp);
        //  cout<<m<<endl;
        double ans=0;
        for (int i=2; i<m; ++i) {
            ans+=Cross(tmp[i-1]-tmp[0],tmp[i]-tmp[0]);
        }
        printf("%.2f\n",ans/2.0);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值