LightOJ 1203 - Guarding Bananas

题意:给定n个点,求从其中一个点看其他所有点的张角的最小值..求凸包就行了..可是我用的时间0.2+s,排倒数了,,难道有其他解法???还是因为我使用了map?


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <string>
#define LL long long
#define DB double
using namespace std;
const int N = 100009;
const DB EPS = 1e-8;
const DB INF = 1e20;
const DB PI = acos(-1.0);
struct cpoint{
    DB x,y;
    void get(){scanf("%lf%lf",&x,&y);}
};
struct cvector{
    DB x,y;
    cvector(DB a,DB b){x=a;y=b;}
};
cvector operator-(cpoint a,cpoint b)
{
    return cvector(a.x-b.x,a.y-b.y);
}
int cmp(cpoint a,cpoint b)
{
    return a.y<b.y||(a.y==b.y&&a.x<b.x);
}
DB x_mult(cpoint a,cpoint b,cpoint p)
{
    return (a.x-p.x)*(b.y-p.y)-(a.y-p.y)*(b.x-p.x);
}
int graham(cpoint p[],int s,cpoint r[])
{
    int len,top=1;
    sort(p,p+s,cmp);
    r[0] = p[0];r[1]= p[1];r[2] = p[2];
    if(s<3) return s;
    for(int i=2;i<s;i++)
    {
        while(top&&x_mult(p[i],r[top],r[top-1])>EPS) top--;
        r[++top] = p[i];
    }
    len = top;r[++top] = p[s-2];
    for(int i=s-3;i>=0;i--)
    {
        while(top!=len&&x_mult(p[i],r[top],r[top-1])>EPS) top--;
        r[++top] = p[i];
    }return top;
}
cpoint p[N],r[N];
DB length(cvector t)
{
    return sqrt(t.x*t.x+t.y*t.y);
}
DB dot(cpoint a,cpoint b,cpoint p)
{
    return (a.x-p.x)*(b.x-p.x)+(a.y-p.y)*(b.y-p.y);
}
DB get(cpoint a,cpoint b,cpoint p)
{
    return acos(dot(a,b,p)/length(a-p)/length(b-p));
}
struct nod{
    int x,y;
    bool operator<(const nod t)const
    {
        return x<t.x||(x==t.x&&y<t.y);
    }
};
map<nod,int> mp;
bool in(cpoint t)
{
    nod c;
    c.x = t.x+0.1;c.y = t.y+0.1;
    if(mp.find(c)!=mp.end()) return false;
    mp[c] = 1;
    return true;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int n,cas,T=1;scanf("%d",&cas);
    while(cas--)
    {
        mp.clear();
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            p[i].get();
            if(!in(p[i])) i--,n--;
        }
        n = graham(p,n,r);
        r[n] = r[0],r[n+1] = r[1];
        DB ans =2*PI;
        for(int i=1;i<=n;i++)
        {
            ans = min(ans,get(r[i-1],r[i+1],r[i]));
        }
        if(n<3) ans = 0;
        printf("Case %d: %.10lf\n",T++,ans/PI*180);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值