poj1912:A highway and the seven dwarfs(凸包)

传送门

题意:
给出平面上的N个点,对于M条直线,依次判断这N个点是否在每条直线的同一侧。是输出GOOD,不是输出BAD。

题解:
凸包+二分。

首先构造出凸包,之后对于一条直线,找出其两条平行线,这两条平行线在凸包上是切线,再判断相切的两个点构成的线段是否与直线相交就行了。

#include<iostream>
#include<set>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const double eps=1e-8;
typedef pair<double,int> pii;
inline bool operator<(const pii &a,const pii &b){
    return a.first-eps<b.first;
}
vector<pii>S;
const int Maxn=1e5+50;
int n,id,tot=1;
struct point{
    double x,y;
    point(double x=0,double y=0):x(x),y(y){}
    friend inline point operator -(const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}
    friend inline double operator *(const point &a,const point &b){return a.x*b.y-a.y*b.x;}
    inline double len()const{return sqrt(x*x+y*y);}
}p[Maxn],q1,q2;
inline bool cmp_ang(const point &a,const point &b){
    double t=(a-p[1])*(b-p[1]);
    if(t!=0)return t>0;
    else return ((a-p[1]).len()<(b-p[1]).len());
}
inline bool inter(point a,point b,point c,point d){
    return ((d-b)*(c-b))*((c-a)*(d-a))>-eps;
}
int main(){
    scanf("%d",&n);
    if(!n){
        while(scanf("%lf%lf%lf%lf",&q1.x,&q1.y,&q2.x,&q2.y)!=EOF)printf("GOOD\n");
        return 0;
    }
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&p[i].x,&p[i].y);
        if(i==1||(p[i].x<p[id].x)||(p[i].x==p[id].x&&p[i].y<p[id].y))id=i;
    }
    if(id!=1)swap(p[1],p[id]);
    sort(p+2,p+n+1,cmp_ang);
    for(int i=2;i<=n;i++){
        while(tot>=2&&(p[i]-p[tot-1])*(p[tot]-p[tot-1])>=0)tot--;
        p[++tot]=p[i];
    }
    p[tot+1]=p[1];
    for(int i=1;i<=tot;i++)S.push_back(make_pair(atan2(p[i+1].y-p[i].y,p[i+1].x-p[i].x),i));
    if(S.size())sort(S.begin(),S.end());
    S.push_back(make_pair((*S.begin()).first+2.0*acos(-1.0),(*S.begin()).second));
    while(scanf("%lf",&q1.x)!=EOF){
        scanf("%lf%lf%lf",&q1.y,&q2.x,&q2.y);
        if(n==0){printf("GOOD");continue;}
        pii t1=*(lower_bound(S.begin(),S.end(),make_pair(atan2(q2.y-q1.y,q2.x-q1.x),0)));
        pii t2=*(lower_bound(S.begin(),S.end(),make_pair(atan2(q1.y-q2.y,q1.x-q2.x),0)));
        if(!inter(p[t1.second],p[t2.second],q1,q2)){printf("GOOD\n");}
        else {printf("BAD\n");}
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值