Double Fence Gym - 101484E (二维凸包)

题目

https://vjudge.net/problem/Gym-101484E

题意

给你两个凸包 判断是否是一个凸包包含另一个凸包,即不相交

思路

两个凸包所有点求一次凸包,看所选点是否是来自同一个凸包

需要注意一点是  共线点要全部算上

代码

 #include<stdio.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN=310000;

struct point
{
    ll x,y;
    int id;
};
point lis[MAXN];
int stac[MAXN],top;

ll cross(point p0,point p1,point p2)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
double dis(point p1,point p2)
{
    return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
bool cmp(point p1,point p2)
{
    ll tmp=cross(lis[0],p1,p2);
    if(tmp>0) return true;
    else if(tmp==0&&dis(lis[0],p1)>dis(lis[0],p2)) return true;
    else return false;
}

void init(int n)
{
    int i,k;
    point p0;
    p0.x=lis[0].x;
    p0.y=lis[0].y;
    p0.id=lis[0].id;
    k=0;
    for(i=1;i<n;i++)
    {
        if( (p0.y>lis[i].y) || ((p0.y==lis[i].y)&&(p0.x>lis[i].x)) )
        {
            p0.x=lis[i].x;
            p0.y=lis[i].y;
            p0.id=lis[i].id;
            k=i;
        }
    }
    lis[k]=lis[0];
    lis[0]=p0;

    sort(lis+1,lis+n,cmp);
}

void graham(int n)
{
    int i;
    if(n==1) {top=0;stac[0]=0;}
    if(n==2)
    {
        top=1;
        stac[0]=0;
        stac[1]=1;
    }
    if(n>2)
    {
        for(i=0;i<=1;i++) stac[i]=i;
        top=1;

        for(i=2;i<n;i++)
        {
            while(top>0&&cross(lis[stac[top-1]],lis[stac[top]],lis[i])<0LL) {
                //if(cross(lis[stac[top-1]],lis[stac[top]],lis[i])==0LL) lis[i].flag|=lis[stac[top]].flag;
                top--;
            }
            top++;
            stac[top]=i;
        }
    }
}


int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i =0;i < n+m;i++)
    {
        scanf("%lld%lld",&lis[i].x,&lis[i].y);
        lis[i].id = i;
    }
    init(n+m);
    graham(n+m);
    int f1=0,f2=0;
    for(int i = 0;i < top;i++)
    {
        if(lis[stac[i]].id < n) f1 = 1;
        else f2 = 1;
    }
    if(f1&&f2) printf("NO\n");
    else printf("YES\n");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值