poj 1228 Grandpa's Estate

//凸包问题,给出n个顶点,问是否唯一确定凸多边形,
//只要构建的凸包每条边上至少包含3个顶点即是唯一
//在构建好凸包后,要特别处理最后一条边,生成凸包时最后一条边包含第一个和最后一个顶点,但其他共线的顶点不会被包含进去,所以需要额外判断
#include <iostream>

#include <algorithm>
#include <cmath>
using namespace std;
struct point
{
int x,y;
}st;
point castle[1005];
double dis(point a,point b)
{
return sqrt(pow(a.x-b.x+0.0,2.0)+pow(a.y-b.y+0.0,2.0));
}
int cmp(const point& a,const point& b)
{
if((b.x-st.x)*(a.y-st.y)==(a.x-st.x)*(b.y-st.y))
return dis(st,a)<dis(st,b);
else
return (b.x-st.x)*(a.y-st.y)<(a.x-st.x)*(b.y-st.y);
}
bool left(point a,point b,point c)
//a,b,c分别为 castle[s[t-1]],castle[s[t]],castle[i],
//如果直线ac的斜率大于ab的斜率,则说明从ab到ac做左转,即ac在ab的逆时针方向,c点才可以加入堆栈中
{

return (c.y-a.y)*(b.x-a.x) >= (b.y-a.y)*(c.x-a.x); //(c.y-a.y)/(c.x-a.x) > (b.y-a.y)/(b.x-a.x)
//要特别注意=的情况,相等说明c在直线ab上,判断左转时这种同直线的情况也要考虑,若只是 > ,则 RE
}

double slope(point a,point b) //求出直线(a,b)的斜率
{

if(a.x==b.x)
return 999999;
else
return (b.y-a.y+0.0)/(b.x-a.x+0.0);
}
double slp[1005];
int main()
{
int n,cases;
cin>>cases;
while(cases--)
{
cin>>n;
int idx=0;
for(int i=0;i<n;++i)
{
cin>>castle[i].x>>castle[i].y;
if(castle[i].y<castle[idx].y||(castle[i].y==castle[idx].y&&castle[i].x<castle[idx].x))
idx=i;
}
if(n<6) //因为每条边上至少包含原多边形的3个顶点,以三角形来计算,三条边至少也得6个顶点
{

cout<<"NO\n";continue;
}
st.x=castle[idx].x;st.y=castle[idx].y;
sort(castle,castle+n,cmp);
int top=-1,s[1005];
s[++top]=0;s[++top]=1;s[++top]=2;
for(int i=3;i<n;++i)
{
while(!left(castle[s[top-1]],castle[s[top]],castle[i]))
--top;
s[++top]=i;
} //此时的栈顶元素一定是第n个点
for(int i=1;i<=top;++i)

slp[i-1]=slope(castle[s[i-1]],castle[s[i]]);
slp[top]=slope(castle[s[0]],castle[s[top]]);
int f=0,ok=1;
for(int i=1;i<=top;++i) //判断是否所有的直线都有3个或以上的点经过
{

if(slp[i]==slp[i-1])
f++;
else if(f==0) //f=0且slp[i]!=slp[i-1],说明该直线只有2个点经过
{

cout<<"NO\n";
ok=0;break;
}
else
f=0; //处理下一条直线
}

if(ok==0)
continue;
if(f==top) //所有的点共线,结果为“NO”
cout<<"NO\n";

else //即当f==0,此时要判断最后一条边(一定经过第1个点和最后一个顶点)是否有3个或以上的点
{

int g=0;
for(int i=1;i<n-1;++i) //i<n-1, slope(castle[n-1],castle[0])与slp[top]相等
if(slope(castle[i],castle[0])==slp[top])

g++;
if(g<1) //最后一条边只有两个顶点,即第1个顶点和第n个顶点,所以最后一条边不满足条件
cout<<"NO\n";

else
cout<<"YES\n";
}
}
return 0;
}

posted on 2011-07-22 19:03  sysu_mjc  阅读(133)  评论(0编辑  收藏  举报

导航