歪日,用了两个凸包板子,就是正确不了,自己思路也没啥问题啊。落泪了,以为是板子的问题,可能是我的问题.
我靠,就在我写一篇“没做出题的失败的博客的时候”,抱着试一试的心态,歪日,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)