UVA11626 Convex Hull
wind_whisper · · 题解
\text{Description}
给出一些凸包上的点,要求你从
\text{Solution}
本题似乎用 Andrew 会更为方便,但蒟蒻还是喜欢简单清新的 Graham...
本题用 Graham 主要的麻烦就在于对凸包上共线的点如何处理。
这篇题解的做法是在共线时按照
input:
1
4
0 0 Y
1 1 Y
2 2 Y
3 10 Y
ans:
4
0 0
1 1
2 2
3 10
output:
4
0 0
2 2
1 1
3 10
一个正确的做法是找到上下凸壳的分界点,然后下凸壳共线时按照距离升序排序,上凸壳共线时按照距离降序排序。
如果哪位有更好的实现欢迎评论或私信。
\text{Code}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
const double eps=1e-10;
const double pi=acos(-1.0);
struct V{
double x,y;
V():x(0),y(0){}
V(double a,double b):x(a),y(b){}
};
inline void input(V &a){scanf("%lf%lf",&a.x,&a.y);}
void print(const V &a,int op=1){printf("%.10lf %.10lf",a.x,a.y);putchar(op?10:32);}
inline V operator + (const V &a,const V &b){return (V){a.x+b.x,a.y+b.y};}
inline V operator - (const V &a,const V &b){return (V){a.x-b.x,a.y-b.y};}
inline V operator * (const double &x,const V &a){return (V){a.x*x,a.y*x};}
inline V operator * (const V &a,const double &x){return (V){a.x*x,a.y*x};}
inline V operator / (const V &a,const double x){return (V){a.x/x,a.y/x};}
inline bool operator == (const V &a,const V &b){return abs(a.x-b.x)<eps&&abs(a.y-b.y)<eps;}
inline bool operator != (const V &a,const V &b){return !(a==b);}
inline double operator * (const V &a,const V &b){return a.x*b.x+a.y*b.y;}
inline double operator ^ (const V &a,const V &b){return a.x*b.y-a.y*b.x;}
inline double len(const V &a){return sqrt(a.x*a.x+a.y*a.y);}
inline bool operator < (const V &a,const V &b){
return a.x<b.x-eps||(abs(a.x-b.x)<eps&&a.y<b.y-eps);
}
const int N=1e5+100;
const int M=505;
int n,m;
int top;
V p[N],zhan[N];
bool cmp(V a,V b){
double d=((a-p[1])^(b-p[1]));
if(abs(d)>eps) return d>0;
else return len(a-p[1])<len(b-p[1]);
}
bool cmp2(V a,V b){
double d=((a-p[1])^(b-p[1]));
if(abs(d)>eps) return d>0;
else return len(a-p[1])>len(b-p[1]);
}
void work(){
n=read();m=0;
V o;char c;
for(int i=1;i<=n;i++){
input(o);scanf(" %c",&c);
if(c=='Y') p[++m]=o;
}
n=m;
sort(p+1,p+1+n);
sort(p+2,p+1+n,cmp);
for(int i=2;i<n;i++){
if(p[i+1].x<p[i].x){//找到分界点,后面重新排序
sort(p+i,p+1+n,cmp2);break;
}
}
printf("%d\n",n);
for(int i=1;i<=n;i++){
printf("%.0lf %.0lf\n",p[i].x,p[i].y);
}
}
signed main(){
#ifndef ONLINE_JUDGE
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
#endif
int T=read();
while(T--) work();
return 0;
}
/*
1
4
0 0 Y
1 1 Y
2 2 Y
3 10 Y
*/