题目链接:https://vjudge.net/problem/POJ-1228
解题思路:
所谓稳定凸包就是不存在凸包外加入一个点使得形成的新凸包还包含原凸包的所有点。
所以要使他是稳定的,那么凸包的每条边都必须有三个点,也就是除了两个端点外边上还有一点,这样如果要在外加入一个点的话必然使得边上的点被消除,所以这样的凸包也就是稳定的了。
#include<math.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n,top,_x,_y;
struct node
{
int x,y;
}s[mx],tubeg[mx],w;
//在向量右侧值为负
int judge(node p1,node p2,node p0)//面积公式判断正负值
{
int ans = (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
return ans;
}
bool cmp(node a,node b)
{
int c = judge(w,b,a);//极角排序,同角度按距离从小到大排
if(!c) return pow(a.x-w.x,2)+pow(a.y-w.y,2) < pow(b.x-w.x,2)+pow(b.y-w.y,2);
return c < 0;
}
bool Graham()
{
bool ok = 0;
for(int i=1;i<n;i++)
{
if(judge(s[i-1],s[i],s[(i+1)%n])!=0)
{
if(!ok) return 0;
ok = 0;
}else ok = 1;
}
return 1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int a,b,p = 0;
for(int i=0;i<n;i++){
scanf("%d%d",&s[i].x,&s[i].y);
if(s[i].y<s[p].y) p = i;
else if(s[i].y==s[p].y&&s[i].x<s[p].x) p = i;
}
if(n<6){
puts("NO");
continue;
}
swap(s[0],s[p]),w.x = s[0].x,w.y = s[0].y;
sort(s+1,s+n,cmp);//以最下左那个坐标为参考坐标做极角排序
int last = n-2;
while(judge(s[0],s[n-1],s[last])==0&&last) last--;
reverse(s+last+1,s+n);//最后一部分如果是共线的话顺序应该是距离长的在前
//与左下角中心的形成三点一线的在凸包中只有开始的点或者最后的点,可以自己去证明
puts(Graham()?"YES":"NO");
}
return 0;
}