凸包模板

题目链接:http://codeforces.com/gym/101484/problem/E

凸包算法

1.先找到y坐标最小的点g,然后再让所有的点都减去g.x和g.y,再对它们进行极角排序

2.排序后的数组为,node[1],node[2],node[3],node[4]......node[n-1],其中node[0]为y坐标最小的点,node[1]和node[n]一定为凸包上的点

3.将node[0],node[1],node[2],入凸包栈,检查栈顶,也就是node[2],判断向量(node[2]-node[1])与(node[3]-node[2])的叉积,也就是他们是左旋转还是右旋转,如果是右旋转,则node[2]不是凸包上的点,node[2]就出栈

4.node[3]入栈,重复3和4的过程

 

极角排序

根据每个点与原点连线和x轴的夹角排序,如果夹角相同,则按照距离排序,都是从小到大

 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
struct Node
{
    ll x,y,fla;
    bool operator <(const Node &a)const
    {
         long double co1=1.0*x/sqrt(x*x+y*y);
         long double co2=1.0*a.x/sqrt(a.x*a.x+a.y*a.y);
         if(a.x*y==a.y*x)//判断夹角是否相同
            return sqrt(x*x+y*y)<sqrt(a.x*a.x+a.y*a.y);
         else
            return co1>co2;
    }
}node[maxn*2],ans[maxn*2];

ll check(Node &a,Node &b,Node &c)//叉积
{
   // cout<<a.fla<<" "<<b.fla<<" "<<c.fla<<endl;
    ll x1=b.x-a.x;
    ll y1=b.y-a.y;
    ll x2=c.x-b.x;
    ll y2=c.y-b.y;
    if(x1*y2-x2*y1>=0)return 1;
    else return 0;
}
int now;
int main()
{
    int n,m;
    ll mix=1e9,miy=1e9,fla;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld %lld",&node[i].x,&node[i].y);
        node[i].fla=i;
        if(node[i].y<=miy)
            miy=node[i].y,fla=i,mix=node[i].x;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%lld %lld",&node[i+n].x,&node[i+n].y);
        node[i+n].fla=i+n;
        if(node[i+n].y<=miy)
            miy=node[i+n].y,fla=i+n,mix=node[i+n].x;
    }
    for(int i=1;i<=m+n;i++)
        node[i].x-=mix,node[i].y-=miy;
    node[0]=node[fla];
    for(int i=fla+1;i<=n+m;i++)
        node[i-1]=node[i];
    sort(node+1,node+n+m);
    ans[0]=node[0];
    ans[1]=node[1];
    ans[2]=node[2];
    now=2;
    for(int i=3;i<n+m;i++)
    {
        while(check(ans[now-1],ans[now],node[i])==0)
            now--;
        now++;
        ans[now]=node[i];
    }
    int nn=n,mm=m;

    for(int i=0;i<=now;i++)
    {
        if(ans[i].fla<=n)nn--;
        else mm--;
    }
    if((nn==n&&mm==0)||(mm==m&&nn==0))cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

  

 

posted @ 2018-10-25 15:55  czh~  阅读(236)  评论(0编辑  收藏  举报