题目链接:
LightOJ 1203 Guarding Bananas
题意:
给出n个点,找到一个点使从这个点看其他所有点所形成的最大夹角最小(视野内能看完其他所有点)。
分析:
先求个凸包,因为这样的点肯定是凸包上的点。然后枚举凸包顶点,凸包顶点和相邻边的另外两个端点所形成的角
肯定能覆盖所有凸包顶点,这样子一来就是转化为求两点对一点所形成的夹角,枚举取最小即可。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <iostream>
using namespace std;
const int MAX_N=101000;
const double INF=1e90;
const double eps=1e-10;
const double PI=acos(-1.0);
int T,n,cases = 0;
struct Point{
double x,y;
Point () {}
Point (double x,double y) : x(x),y(y) {
}
Point operator + (const Point& rhs) const {
return Point(x+rhs.x,y+rhs.y);
}
Point operator - (const Point& rhs) const {
return Point(x-rhs.x,y-rhs.y);
}
Point operator * (const double d) const {
return Point(d*x,d*y);
}
double dis(const Point& rhs) const { //两点距离
return sqrt((x-rhs.x)*(x-rhs.x)+(y-rhs.y)*(y-rhs.y));
}
double dot(const Point& rhs) const { //点积、内积
return (x*rhs.x+y*rhs.y);
}
double cross(const Point& rhs) const { //叉积、外积
return (x*rhs.y-y*rhs.x);
}
double rad(const Point& a, const Point& b) const {
Point p = *this;
return fabs(atan2(fabs((a - p).cross(b - p)), (a - p).dot(b - p)));
}
}point[MAX_N],vertex[MAX_N];
inline bool cmp_x(const Point a,const Point b)
{
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
inline int Andrew()
{
sort(point,point+n,cmp_x);
int k=0;
for(int i=0;i<n;i++){
while(k>1&&(vertex[k-1]-vertex[k-2]).cross(point[i]-vertex[k-1])<=0){
k--;
}
vertex[k++]=point[i];
}
int m = k;
for(int i=n-2;i>=0;i--){
while(k>m&&(vertex[k-1]-vertex[k-2]).cross(point[i]-vertex[k-1])<=0){
k--;
}
vertex[k++]=point[i];
}
if(k>1) k--;
return k;
}
int main()
{
scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%lf%lf", &point[i].x, &point[i].y);
}
printf("Case %d: ", ++cases);
int total = Andrew();
if(total == 1 || total == 2){
printf("%.6lf\n", 0);
continue;
}
double ans = 400;
vertex[total] = vertex[0];
for(int i = 0; i < total; i++){
int pre = (i - 1 + total) % total;
int nxt = (i + 1 + total) % total;
double tmp = vertex[i].rad(vertex[pre], vertex[nxt]);
ans = min(ans, tmp);
}
printf("%.6lf\n", ans / PI * 180.0);
}
}