| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 11508 | Accepted: 3188 |
Description
Input
Output
Sample Input
1 6 0 0 1 2 3 4 2 0 2 4 5 0
Sample Output
NO
Source
题意:输入一个凸包上的点(没有凸包内部的点,要么是凸包顶点,要么是凸包边上的点),判断这个凸包是否稳定。所谓稳定就是判断能不能在原有凸包上加点,得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点。
题解:凸包的每条边包含端点至少有3个点时时稳定凸包。我们只需判断凸包的每条边是否存在剩下的点在边上。
#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#define INF 0x3f3f3f3f
#define _sign(x) ((x)>eps?1:((x)<-eps?2:0))
using namespace std;
const int MAXN = 1030;
struct Point {
double x,y;
Point() {}
Point(double _x,double _y) {
x = _x;
y = _y;
}
Point operator -(const Point &b)const {
return Point(x - b.x,y - b.y);
}
//叉积
double operator ^(const Point &b)const {
return x*b.y - y*b.x;
}
//点积
double operator *(const Point &b)const {
return x*b.x + y*b.y;
}
//绕原点旋转角度B(弧度值),后x,y的变化
void transXY(double B) {
double tx = x,ty = y;
x = tx*cos(B) - ty*sin(B);
y = tx*sin(B) + ty*cos(B);
}
};
Point L[MAXN];
int Stack[MAXN],top;
int n;
double dist(Point a,Point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double multi(Point p1, Point p2, Point p3) {
return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
}
int sgn(double x) {
if(fabs(x)<1e-12)return 0;
if(x<0)return -1;
return 1;
}
//相对于L[0]的极角排序
bool _cmp(Point p1,Point p2) {
double tmp =(p1-L[0])^(p2-L[0]);
if(sgn(tmp)>0)return true;
else if(sgn(tmp)==0&&sgn(dist(p1,L[0])-dist(p2,L[0]))<= 0)
return true;
else return false;
}
void Graham(int m) {
if(m<=1)return;
Point p0;
int k = 0;
p0 = L[0];
//找最下边的一个点
for(int i=1; i<m; i++) {
if((p0.y>L[i].y)||(p0.y==L[i].y&&p0.x>L[i].x)) {
p0 = L[i];
k = i;
}
}
swap(L[k],L[0]);
sort(L+1,L+m,_cmp);
if(m==1) {
top=1,Stack[0] = 0;
return;
}
if(m==2) {
top=2,Stack[0]=0,Stack[1]=1;
return ;
}
Stack[0]=0;
Stack[1]=1;
top=2;
for(int i=2; i<m; i++) {
while(top>1&&sgn((L[Stack[top-1]]-L[Stack[top-2]])^(L[i]-L[Stack[top-2]]))<=0)
top--;
Stack[top++] = i;
}
}
int main() {
//freopen("test.in","r",stdin);
int t;
cin>>t;
while(t--) {
scanf("%d",&n);
for(int i=0; i<n; i++) {
scanf("%lf%lf",&L[i].x,&L[i].y);
}
if(n<6) {
printf("NO\n");
continue;
}
Graham(n);
bool flag=1;
for(int i=0; i<top; i++) {
int u=Stack[i],v=Stack[(i+1)%top];
flag=1;
///判断剩下的点是否存在至少一点在边上
for(int j=0; j<n; j++) {
if(j==u||j==v)continue;
if(multi(L[u],L[j],L[v])==0) {
flag=0;
break;
}
}
if(flag)break;
}
printf("%s\n",flag==0?"YES":"NO");
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/acm_baihuzi/article/details/47430735