• 凸包模板


    题目链接: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;
    }
    

      

  • 相关阅读:
    DNN SEO专题 (收集)
    DataTable或者DataSet匯出Excel
    用C#制作PDF文件全攻略(转)
    BlogEngine资料收集
    DNN架构解析(收集)
    Community Server:快速找到需要修改的文件[技巧]
    通用的分页存储过程
    DataTable/DataSet汇出Excel
    百试不爽的30条职场经验(转)
    等宽字体
  • 原文地址:https://www.cnblogs.com/carcar/p/9850390.html
Copyright © 2020-2023  润新知