HDU2469 UVALive4356 UVA1432 Fire-Control System

链接

http://acm.hdu.edu.cn/showproblem.php?pid=2469

题解

本来以为是一道很简单的休闲题,结果调试了一晚上+一上午
其实算法没什么难的,因为最小扇形的半径肯定等于某个点到原点的距离,所以直接 O ( n ) 枚举半径,然后 O ( n ) 扫描一下就行了,时间复杂度 O ( n 2 )
一个技巧就是,把整个数组复制一遍,后面的那一段的角度加上 2 π ,这样就好处理很多
一个很可恶的事情就是, k 可能等于 0 ,我就是没注意到这一点,才 W A 的要死
话说 k = 0 真的有意义吗??

代码

//几何题
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cmath>
#define maxn 5010
#define inf 1e60
#define eps 1e-8
#define sqr(x) ((x)*(x))
#define PI 3.1415926535897932384626433832795
using namespace std;
struct point
{
    int x, y, r2;
    double theta;
    void init(){theta=atan2(y,x);r2=sqr(x)+sqr(y);}
    bool operator<(point a){return theta<a.theta-eps;}
}pt[maxn<<1];
int n, k;
double ans;
int read(int x=0)
{
    char c, f=1;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
    return f*x;
}
void init()
{
    int i;
    for(i=1;i<=n;i++)pt[i].x=read(), pt[i].y=read(), pt[i].init();
    sort(pt+1,pt+n+1);
    for(i=1;i<=n;i++)pt[n+i]=pt[i], pt[n+i].theta+=2*PI;
}
void work()
{
    int i, j, p1, p2, cnt, alpha, r2;
    ans=inf;
    for(i=1;i<=n;i++)
    {
        r2=pt[i].r2;
        for(p1=1, p2=2, cnt=pt[1].r2<=r2;p1<=n;p1++)
        {
            for(;cnt<k and p2<p1+n;p2++)if(pt[p2].r2<=r2)cnt++;
            if(cnt==k)ans=min(ans,(pt[p2-1].theta-pt[p1].theta)*r2/2.0);
            if(pt[p1].r2<=r2)cnt--;
        }
    }
}
int main()
{
    int c;
    for(n=read(),k=read(),c=1;n;n=read(),k=read(),c++)
    {
        printf("Case #%d: ",c);
        init();
        if(k==0)ans=0;
        else work();
        printf("%.2lf\n",ans+eps);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/81297391