Poj1228(稳定凸包)

题目链接: http://poj.org/problem?id=1228

 

题意:给定一些点,问这些点能不能够成稳定的凸包,这有点不明不白的,我也是看了别人的报告才搞明白题意的,就是如果凸包上的一条边如果不包 含三个以上的点,它就是可以被向外扩展的.

 

解题:

弄明白了题意,以为会很简单了,直接扫描求凸包就行了,而且是不用退栈的过程,后来在实现过程中才发现,即使给出的所有点都在凸包上,也是不能够一次循环下来就入栈所有的点,因为,所有的点只是按相对原点(这里指左下角的点)的转角进行排序,并且又是距离进的排在前面,而在以后或者最后一条边下来的时候,如果它直通原点,则一定会首先入栈那些距原点近的点,这样所有点的入栈顺序就跟所需求的顺序混乱了~所以在入栈每点的时候,首先进行再次的扫描,然后对相对于原点相同转角的所有点进行二次排序,其实这个排序也可以放在求凸包之前的,而把第一次排序中的距离换成远距离放在前面就行了~

 

呃,因为输入WA了好几次,对于输入n,直接判断它小于6,而没有接收后面的n个点,尴尬~

 

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #define M 1008 typedef struct{ int x,y; }Point; const double eps = 1e-8; Point p[M]; int stk[M]; int ps[M]; int num,flag; int n,top,i,j; double xyDis(Point p,Point q) {//这个什么距离来着?~~~ >< return fabs(p.x-q.x)+fabs(p.y-q.y); } double Multi(Point p,Point q,Point o) {//叉积 return (p.x-o.x)*(q.y-o.y)-(q.x-o.x)*(p.y-o.y); } int Cmp(const void *x,const void *y) {//按左下角点的逆时针转角排序 Point *a=(Point *)x; Point *b=(Point *)y; double d=Multi(*a,*b,p[0]); if(fabs(d)<eps) return xyDis(*a,p[0])>xyDis(*b,p[0])?1:-1; return d<0?1:-1; } int cmp(const void *x,const void *y) {//按当前栈顶点的逆时针转角排序 Point *a=(Point *)x; Point *b=(Point *)y; double d=Multi(*a,*b,p[i-1]); if(fabs(d)<eps) return xyDis(*a,p[i-1])>xyDis(*b,p[i-1])?1:-1; return d<0?1:-1; } int main() { Point tmp; int t,k; double d; scanf("%d",&t); while(t--){ scanf("%d",&n); /* if(n<6){ puts("NO");continue; }*/ for(i=0,k=0;i<n;i++){ scanf("%d%d",&p[i].x,&p[i].y); if(p[i].x<p[k].x||p[i].x==p[k].x&&p[i].y<p[k].y) k=i; } if(n<6){ //因为把这一名加在点的输入这前,一直WA,改过来后就AC了~~~这个真是的~ puts("NO");continue; } tmp=p[0],p[0]=p[k],p[k]=tmp;//交换首元素 qsort(p+1,n-1,sizeof(p[0]),Cmp);//按相对p[0]的转角逆时针排序 p[n++]=p[0];//因为要判断每条边是否要含有三个点以上,最后一条边特殊考虑 for(top=i=0;i<2;i++) stk[top++]=i; ps[num=0]=0;//初始化第一条边,这里忽略了每条边的两端点 flag=1;//flag 标记是否 //这里需要说明的是,如果当前的点不能加入可以构成凸包的栈, //那么这些点就不能构成稳定的凸多边形,所以没有退栈操作 for(i=2;i<n&&flag;i++){ //加入新结点的时候按照当前栈顶的逆时针,在这里进行排序 for(j=i+1;j<n&&fabs(Multi(p[j],p[i],p[0]))<eps;j++); qsort(p+i,j-i,sizeof(p[0]),cmp); d=Multi(p[stk[top-2]],p[stk[top-1]],p[i]); if(fabs(d)<eps){//如果该点在之前的同一条边上 stk[top++]=i; ps[num]++; } else if(d>0){//发现了新边 ps[++num]=0; stk[top++]=i; } else flag=0;//当前点不在凸包上 } if(top<n) flag=0; for(i=0;i<=num&&flag;i++) flag=ps[i]; puts(flag?"YES":"NO"); } return 0; }  

你可能感兴趣的:(struct,ini,扩展)