版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/84110526
题目链接:poj 1288
题意:给出n个原来凸包的点,问能否根据这n个点推测出原来的凸包,若能,输出YES。
题解:我们先求出这n个点的凸包来,然后在判断新凸包每条边都有其它点在,那么可以说明此边是确定边,因为要想让一个凸包稳定,当且仅当凸包上任意一条边有3个以上的木桩(包括端点)。
例如这图,假设新凸包点为A,C,D,很容易可以看到CD边没有其它点,那么这条边就是不确定的,它有可能还有个F点(这个点未知)。
还注意一点的是: 小于6个点,一定不能成稳定凸包,因为最小是三角形的凸包,每条边之间有一个点,那么这都有六个点了。
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1010;
struct point{
int x,y;
point(){}
point(int _x,int _y){
x=_x;y=_y;
}
}p[maxn],ch[maxn];
int n;
point operator + (point a,point b) { return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) { return point(a.x-b.x,a.y-b.y);}
point operator * (point a,int p) { return point(a.x*p,a.y*p);}
point operator / (point a,int p) { return point(a.x/p,a.y/p);}
bool operator < (const point &a,const point &b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
const double esp=1e-8;
int dcmp(double x)
{
if(fabs(x)<esp) return 0;
else return x<0?-1:1;
}
bool operator == (const point &a,const point b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
int Cross(point a,point b) { return a.x*b.y-a.y*b.x;}
int Dot(point a,point b) { return a.x*b.x+a.y*b.y;}
bool cmp(point a,point b){
return (a.y<b.y||(a.y==b.y&&a.x<b.x));
}
int tot;
void andrew(int n)
{
sort(p,p+n,cmp);
tot=-1;
for(int i=0;i<n;i++)
{
while(tot>0&&Cross(ch[tot]-ch[tot-1],p[i]-ch[tot])<=0)
tot--;
ch[++tot]=p[i];
}
for(int i=n-2,k=tot;i>=0;i--)
{
while(tot>k&&Cross(ch[tot]-ch[tot-1],p[i]-ch[tot-1])<=0)
tot--;
ch[++tot]=p[i];
}
}
///判断点在线段上(不包括端点)
bool Onsegment(point p,point a1,point a2)
{
return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}
bool judge(point a,point b) ///判断ab边是否稳定
{
for(int i=0;i<n;i++){
if(Onsegment(p[i],a,b)) return true;
}
return false;
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
if(n<6){ ///小于6个点,一定不能组成稳定的凸包
puts("NO");continue;
}
andrew(n); ///根据这n个点构造凸包
bool flag=true;
for(int i=1;i<=tot&&flag;i++)
{
if(!judge(ch[i],ch[i-1])){ ///判断ch[i]ch[i-1]这条边是否稳定
flag=false;break;
}
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}