这....好多坑啊...照着学长的代码抄的(捂脸)
1、求凸包的时候 一个点返回的凸包时空的。我人傻了。
2、我一开始是求非严格凸包的点数与n进行比较,及其傻逼!n个点共线的时候会求出来诡异的结果。
所以还是要求凸包然后每个点进行判断啊。
思路很神妙啊!比我的不知道神妙到哪里去了。。
首先先看凸包的边上是否严格存在点嘛,
然后枚举两条边,
这两条边只可能是相邻的,或者中间间隔一条边并且这条边上没有点。
然后考虑check,一个显然的性质是凸包边数比较多的时候就GG了,可以盲猜一下是6
说真的我一开始虽然可能注意到了这条性质但是完全没有想到可以使问题简化这么多。
然后我们看看另一边有几个点,以及能否连出来一个三角形,,这边好zz啊,
比方说y+1到x中间有两个点的话,我们要判这两个点的斜率和x,x+1 以及 y,y+1能不能连成三角形
唔.没了,
请自觉忽略#define
#include <bits/stdc++.h>
#define yxn inline
#define INF 19970404
using namespace std;
typedef long long db;
yxn int sign(db k){
if (k>0) return 1; else if (k<0) return -1; return 0;
}
yxn int cmp(db k1,db k2){return sign(k1-k2);}
yxn int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}
struct point{
db x,y;
point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
point operator * (db k1) const{return (point){x*k1,y*k1};}
bool operator < (const point k1) const{
int a=cmp(x,k1.x);
if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
}
};
yxn int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
yxn db cross(point k1,point k2){ return k1.x*k2.y-k1.y*k2.x;}
yxn db dot(point k1,point k2){ return k1.x*k2.x+k1.y*k2.y;}
yxn int onS(point k1,point k2,point q){return inmid(k1,k2,q)&&sign(cross(k1-q,k2-k1))==0;}
yxn vector<point> ConvexHull(vector<point>&A,int flag=1){ // flag=0 不严格 flag=1 严格
int n=A.size(); vector<point>ans(n*2);
sort(A.begin(),A.end()); int now=-1;
for (int i=0;i<A.size();i++){
while (now>0&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
ans[++now]=A[i];
} int pre=now;
for (int i=n-2;i>=0;i--){
while (now>pre&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
ans[++now]=A[i];
} ans.resize(now); return ans;
}
int n,vis[100005];
point p[100005];
vector<point> v;
yxn bool check(int x,int y){
int m = v.size();
db p1 = cross(v[(x+1)%m]-v[x],v[(y+1)%m]-v[y]);
if(p1==0)return false;
if(p1<0)swap(x,y);
if((x+1)%m!=y&&(x+2)%m!=y)return false;
if((x+2)%m==y&&vis[(x+1)%m])return false;
int cnt=0;
for(int i=(y+1)%m;i!=x;i=(i+1)%m){
cnt++;
}
if(cnt>=4)return false;
else if(cnt==3){
if(vis[(y+1)%m]||vis[(y+3)%m])return false;
if(cross(v[(y+1)%m]-v[y],v[(y+3)%m]-v[(y+2)%m])>0&&cross(v[(y+3)%m]-v[(y+2)%m],v[(x+1)%m]-v[x])>0)return true;
return false;
}else if(cnt==2){
if(vis[(y+1)%m]&&vis[(y+2)%m])return false;
if(vis[(y+1)%m]&&cross(v[(y+2)%m]-v[(y+1)%m],v[(x+1)%m]-v[x])<=0)return false;
if(vis[(y+2)%m]&&cross(v[(y+1)%m]-v[y],v[(y+3)%m]-v[(y+2)%m])<=0)return false;
return true;
}
return true;
}
yxn bool check(){
for(int i=0;i<n;i++){
bool f=0;
for(int j=0;j<v.size();j++){
if(onS(v[j],v[(j+1)%v.size()],p[i]))f=1;
}
if(!f)return false;
}
return true;
}
int main(){
while (scanf("%d",&n)&&n){
v.clear();
for(int i=0;i<n;i++)scanf("%lld%lld",&p[i].x,&p[i].y),v.push_back(p[i]);
v=ConvexHull(v,1);
if(v.size()>6)printf("NO
");
else if(v.size()<=2)printf("YES
");
else if(!check())printf("NO
");
else{
int m = v.size();
for(int i=0;i<m;i++)vis[i]=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(cross(v[(i+1)%m]-v[i],p[j]-v[i])==0&&dot(p[j]-v[i],p[j]-v[(i+1)%m])<0) {
vis[i] = 1;
break;
}
}
}
bool f=0;
for(int i=0;i<v.size()&&!f;i++){
for(int j=i+1;j<v.size()&&!f;j++){
f|=check(i,j);
}
}
if(f)printf("YES
");
else printf("NO
");
}
}
}