凸包板子试炼(玄学过题)

歪日,用了两个凸包板子,就是正确不了,自己思路也没啥问题啊。落泪了,以为是板子的问题,可能是我的问题.

我靠,就在我写一篇“没做出题的失败的博客的时候”,抱着试一试的心态,歪日,AC了。什么玄学过题.

在做这题的时候,一个小技巧:在判断三点共线时,可以用利用叉积为0来判断三点共线。

/*
	B Convex Polygon 
	二维几何:判断所给的点是否为凸多边形.并按顺时针顺序输出点(从最接近(0,0)的点开始输出)
	若为否(三点共线或不为凸多边形)输出"ERROR". 
*/

/*
题目实际上没有所谓的 “非法 ”输入。
题目要判断是输入的所有点能否构成一个凸多边形,并且任意 3点不共线。 
先判断点数 ≥3,然后O(n^3)暴力判断三点共线,最后求凸包判断凸包上的点是否等于总点数即可.
*/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 110;
const double eps = 1e-7;

struct Point {
    
    
    int x, y;
    Point(int x = 0,int y = 0):x(x),y(y){
    
    }
};
typedef Point Vector;
Point lst[maxn];
int stk[maxn], top;
Vector operator - (Point A, Point B){
    
    
    return Vector(A.x-B.x, A.y-B.y);
}
int sgn(int x){
    
    
    if(x == 0)
        return 0;
    if(x < 0)
        return -1;
    return 1;
}
int Cross(Vector v0, Vector v1) {
    
    
    return v0.x*v1.y - v1.x*v0.y;
}
int Dis(Point p1, Point p2) {
    
     //计算 p1p2的 距离的平方 
    return (p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y);
}
bool cmp(Point p1, Point p2){
    
     //极角排序函数 ,角度相同则距离小的在前面
    int tmp = sgn(Cross(p1 - lst[0], p2 - lst[0]));
    if(tmp > 0)
        return true;
    if(tmp == 0 && Dis(lst[0], p1) < Dis(lst[0], p2))
        return true;
    return false;
}

void Graham(int n) {
    
           // n为点的个数.       下标为 0 - n-1 
    int k = 0;
    Point p0;
    p0.x = lst[0].x;
    p0.y = lst[0].y;
    for(int i = 1; i < n; ++i) {
    
    
        if( (p0.y > lst[i].y) || ((p0.y == lst[i].y) && (p0.x > lst[i].x)) ) {
    
    
            p0.x = lst[i].x;
            p0.y = lst[i].y;
            k = i;
        }
    }
    lst[k] = lst[0];
    lst[0] = p0;
    sort(lst + 1, lst + n, cmp);
    stk[0] = 0;
    stk[1] = 1;
    top = 2;
    for(int i = 2; i < n; ++i) {
    
    
        while(top > 1 && Cross(lst[stk[top - 1]] - lst[stk[top - 2]], lst[i] - lst[stk[top - 2]]) <= 0)
            --top;
        stk[top] = i;
        ++top;
    }
    return;
}
//typedef Point Vector;
//Vector operator - (Point A, Point B){
    
    
//    return Vector(A.x-B.x, A.y-B.y);
//}
//bool operator < (const Point& a, const Point& b){
    
    
//    if(a.x == b.x)
//        return a.y < b.y;
//    return a.x < b.x;
//}
//int Cross(Vector v0, Vector v1) {
    
    
//    return v0.x*v1.y - v1.x*v0.y;
//}

//计算凸包,输入点数组为 p,个数为 n, 输出点数组为 ch。函数返回凸包顶点数
//如果不希望凸包的边上有输入点,则把两个 <= 改为 <
//在精度要求高时建议用dcmp比较
//输入不能有重复点,函数执行完后输入点的顺序被破坏
//Point lst[maxn];
//Point stk[maxn], top;
//int ConvexHull(int n) {
    
    
//    sort(lst, lst+n);
//    int m = 0;
//    for(int i = 0; i < n; ++i) {
    
    
//        while(m > 1 && Cross(stk[m-1] - stk[m-2], lst[i] - stk[m-2]) < 0) {
    
    
//            m--;
//        }
//        stk[m++] = lst[i];
//    }
//    int k = m;
//    for(int i = n-2; i>= 0; --i) {
    
    
//        while(m > k && Cross(stk[m-1] - stk[m-2], lst[i] - stk[m-2]) < 0) {
    
    
//            m--;
//        }
//        stk[m++] = lst[i];
//    }
//    if(n > 1)
//        --m;
//    return m;
//}

signed main()
{
    
    
	int x,y;
	int k = 0;
	while(~scanf("%d,%d,",&x,&y)){
    
    
		lst[k++] = {
    
    x,y};
	}
	bool f = 1;
	if(k<3)    f = 0;
	else{
    
    
		for(int i=0;i<k;i++){
    
    
			if(!f)	break;
			for(int j=i+1;j<k;j++){
    
    
				if(!f)	break;
				for(int p=j+1;p<k;p++){
    
    
					if(Cross(lst[i]-lst[j],lst[i]-lst[p])==0){
    
    
						f = 0;
						break;
					}
				}		
			}		
		}		
		if(f){
    
    
			Graham(k);
			if(k!=top)	f = 0;
		}
	}	
	if(f){
    
    
		int id = -1;
		int mi = 10000000.00;        //距离的平方. 
		Point w;
		w.x = 0,w.y = 0;
		for(int i=0;i<k;i++){
    
    
			if(Dis(lst[i],w)<mi){
    
    
				id = i;
				mi = Dis(lst[i],w);
			}
		}
		printf("%d,%d,",lst[id].x,lst[id].y);
		int o = 1;
		// 按照一个方向输出 (逆时针)
		for(int i=k-1;i>id;i--){
    
    
			o++;
			if(o!=k)	printf("%d,%d,",lst[i].x,lst[i].y);
			else	printf("%d,%d",lst[i].x,lst[i].y);
		}		
		for(int i=id-1;i>=0;i--){
    
    
			o++;
			if(o!=k)	printf("%d,%d,",lst[i].x,lst[i].y);
			else	printf("%d,%d",lst[i].x,lst[i].y);
		}
	}else{
    
    
		printf("ERROR");
	}	
	return 0;
} 
// 0,0,2,0,1,1,1,2
//(P[i].x==P[j].x && P[j].x==P[p].x) || (fabs(((double)P[p].y-P[j].y)/((double)P[p].x-P[j].x))-fabs(((double)P[i].y-P[j].y)/((double)P[i].x-P[j].x))<=1e-2)

猜你喜欢

转载自blog.csdn.net/m0_50435987/article/details/121277590