凸包模板
题目链接: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;
}

浙公网安备 33010602011771号