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