题目的意思不难理解,就是求凸包中最小角度
首先构造凸包,之后求最小的角度(<180)
注意有一个陷阱,当角度为180度时,假设图形中仅仅只有一个点,实际的角度应该是0度,这点需要特判.
WA了一天才发现.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
const double PI=acos(-1);
const int maxn=1e5+10;
const double INF=180;
const double eps=1e-10;
int n;
int top;
using namespace std;
int sgn(double x){
if(fabs(x)<eps)
return 0;
return x>0 ? 1:-1;
}
struct point{
double x,y;
point(){}
point(double _x,double _y){
x=_x;
y=_y;
}
};
typedef point vector;
vector operator- (point a,point b){
return point(a.x-b.x,a.y-b.y);
}
double operator * (vector a,vector b){
return a.x*b.x+a.y*b.y;
}
double operator ^ (vector a,vector b){
return a.x*b.y-a.y*b.x;
}
bool operator < (point a,point b){
return a.x==b.x && a.y<b.y ||a.x<b.x;
}
double dis(point a,point b){
return hypot(a.x-b.x,a.y-b.y);
}
point p[maxn];
point stack[maxn];
bool cmp(point a,point b){
int d=sgn((a-p[0])^(b-p[0]));
return d>0 || d==0 && sgn(dis(a,p[0])-dis(b,p[0]))<0;
}
double len(vector a){
return hypot(a.x,a.y);
}
double Angle(point a,point b,point p){
vector A=p-a;
vector B=p-b;
return 360.0/(2*PI)*acos((A*B)/(len(A)*len(B)));
}
void graham(){ //不需要考虑n=1和n=2的情况
stack[0]=p[0];
stack[1]=p[1];
top=2;
for(int i=2;i<n;i++){
while(top>1&&sgn((stack[top-1]-stack[top-2])^(p[i]-stack[top-2]))<=0 )
top--;
stack[top]=p[i];
top++;
}
}
double solve(){ //graham-scan
for(int i=0;i<n;i++)
if(p[i]<p[0])
swap(p[0],p[i]);
sort(p+1,p+n,cmp);//极角排序
graham();
double min=INF;
for(int i=0;i<top;i++){
if(Angle(stack[(i-1+top)%top],stack[(i+1)%top],stack[i]) < min)
min=Angle(stack[(i-1+top)%top],stack[(i+1)%top],stack[i]);
}
return min;
}
int main(){
//freopen("input1203.txt","r",stdin);
int T,cnt=0;
scanf("%d",&T);
while(T--){
double angle;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if(n==1||n==2)
angle=0;
else
angle=solve();
if(sgn(angle-180.0)==0) //特判
angle=0;
printf("Case %d: %.7lf\n",++cnt,angle);
}
}