zoukankan      html  css  js  c++  java
  • URAL 1775 B

    B - Space Bowling
    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87643#problem/B

    Description

    The inhabitants of planets orbiting around the pulsar PSR 2010+15 enjoy playing space bowling. A few cylindrical pins of unit diameter are set on a huge field. A player chooses a certain point of the field and rolls a ball from this point, trying to destroy as many pins as possible. After the ball is released, it rolls in a straight line, touching the surface all the time before rolling away from the field. If the ball touches a pin, this pin dematerializes, and the ball doesn't change direction. To score a strike, the player has to destroy at least k pins in one shot.
    Unfortunately, aliens haven't yet invented a machine that would return the balls that rolled away from the field. Instead, they use a machine that materializes a new ball from vacuum before each shot. A player enters the diameter and in a second he obtains a ball of exactly the same diameter.
    It is time for an alien Vas-Vas to roll a ball. There are n pins standing on the field at the moment. Help Vas-Vas to determine the minimal diameter of a ball, he can score a strike with.
     

    Input

    The first line contains space-separated integers n and k (1 ≤ k ≤ n ≤ 200) . The i-th of following n lines contains space-separated integersxi and yi (−10 5 ≤ xiyi ≤ 10 5) , which are the coordinates of the centers of pins. All pins are situated at different points.

    Output

    Output the minimal possible diameter of a ball which can be used to score a strike, with absolute or relative error not exceeding 10 −6. If a strike can be scored with a ball of arbitrarily small diameter, output “0.000000”.

    Sample Input

    5 4
    0 4
    0 6
    6 4
    6 6
    3 0

    Sample Output

    1.0000000000

    HINT

    题意

    平面上有n个直径为1的圆,然后让你飞出一个球,要求触碰至少k个圆,问这个球的半径至少为多少

    题解

    直接暴力枚举两个圆,然后直线方向就是这两个圆的中垂线,然后暴力算距离,取第k大的就好了

    有一些小细节

    代码前面都是模板,无视就好了

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <complex>
    #include <vector>
    using namespace std;
    
    
    const double eps = 1e-10; //精度控制
    const double pi = acos(-1);
    
    int dcmp(double p) // 三态比较, 负数返回 -1 , 0 返回 0 , 正数返回 1 
    {
       if (fabs(p) < eps) return 0;
       else return p < 0 ? -1 : 1;
    }
    
    inline double Deg2Rad(const double & p) // 角度转弧度
    {
        return pi*p/180.0;
    }
    
    inline double Rad2Deg(const double & p) // 弧度转角度
    {
        return p * 180.0 / pi;
    }
    
    
    struct Point
    {
       long long x , y ;
       Point (double x = 0. , double y = 0.)
       {
            this->x = x , this->y = y;
       }
       //***********重载函数*****************
       friend Point operator + (const Point & T1, const Point & T2)
       {
            return Point(T1.x + T2.x , T1.y + T2.y);
       }
       friend Point operator - (const Point & T1, const Point & T2)
       {
            return Point(T1.x - T2.x , T1.y - T2.y);
       }
       friend Point operator * (const Point & T1 , const double p)
       {
            return Point(T1.x * p , T1.y * p);
       }
       friend Point operator * (const Point & T1 , const int p)
       {
            return Point(T1.x * p , T1.y * p);
       }
       friend bool operator == (const Point & T1 , const Point & T2) // 三态比较,精度较高
       {
            return dcmp(T1.x - T2.x) == 0 && dcmp(T1.y - T2.y) == 0;
       }
       friend ostream& operator << (ostream & os,const Point & x)
       {
             os << "x is " << x.x << " y is " << x.y;
          return os;
       }
       //************************************
    };
    
    
    typedef Point Vector;
    double Dot(const Vector & T1 , const Vector & T2)
    {
        return T1.x * T2.x + T1.y * T2.y;
    }
    
    double Length(const Vector & T1)
    {
        return sqrt(Dot(T1,T1));
    }
    
    double Angle(const Vector & T1 , const Vector & T2)
    {
        return acos(Dot(T1,T2)/ Length(T1) / Length(T2));
    }
    
    double Cross(const Vector & T1, const Vector & T2)
    {
        return T1.x * T2.y - T2.x * T1.y;
    }
    
    double Area2(const Point & T1 , const Point & T2, const Point & T3)
    {
        return Cross(T3-T1,T2-T1);
    }
    
    // 将T1向量绕着起点逆时针旋转 rad 弧度
    Vector Rotate(const Vector & T1 , const double rad)
    {
        return Vector(T1.x*cos(rad) - T1.y * sin(rad) , T1.x*sin(rad) + T1.y*cos(rad));
    }
    
    // 返回向量T1的单位向量,调用时确保向量长度不为 0
    Vector Normal(const Vector & T1)
    {
        double L = Length(T1);
        return Vector(T1.x/L,T1.y/L);
    }
    
    bool cmp1(const Point & a,const Point & b)
    {
        return a.x < b.x || (dcmp(a.x-b.x) == 0 && a.y < b.y);
    }
    
    //按照极角排序
    bool cmp2(const Point & a,const Point & b)
    {
        double t1 = atan2(a.y,a.x);
        double t2 = atan2(b.y,b.x);
        if (t1 < 0) t1 += 360.0;
        if (t2 < 0) t2 += 360.0;
        return t1 < t2;
    }
    
    // 点 A 到 点 u 和点 v 组成的直线的距离
    double DistanceToLine(const Point & A , const Point & u , const Point &v)
    {
        Vector v1(A-u) , v2(v-u);
        return fabs(Cross(v1,v2)) / Length(v2);
    }
    
    double DistanceToSegment(const Point & A,const Point & u,const Point & v)
    {
        if (u == v) return Length(A-u);
        Vector v1 = v - u , v2 = A - u , v3 = A - v;
        if (dcmp(Dot(v1,v2)) < 0) return Length(v2);
        else if(dcmp(Dot(v1,v3)) > 0) return Length(v3);
        else return fabs(Cross(v1,v2)) / Length(v1);
    }
    
    
    // 求两直线交点 , Line A上一点a , 向量 va , Line B上一点 b ,向量vb
    Point GetLineIntersection(const Point & a , const Vector & va, const Point & b , const Vector & vb) 
    {
      Vector u = a-b;
      double t = Cross(vb, u) / Cross(va, vb);
      return a+va*t;
    }
    
    // 规范相交判断
    bool SegmentProperIntersection(const Point & a1,const Point & a2,const Point & b1,const Point & b2)
    {
        double c1 = Cross(b2-b1,a1-b1) , c2 = Cross(b2-b1,a2-b1) , c3 = Cross(a2-a1,b1-a1) , c4 = Cross(a2-a1,b2-a1);
        return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
    }
    
    // 判断点p是否在 a1 和 a2构成的线段上( 不包括端点 )
    bool IsPointOnSegment(const Point & p,const Point & a1 , const Point & a2)
    {
        return dcmp(Cross(a1-p,a2-p)) == 0 && Dot(a1-p,a2-p) < 0; 
    }
    
    // Pay attention !!!
    // 下面的多边形函数带入的多边形点集必须全部为多边形上的点 , 且 必须已经按照极坐标排序(逆时针)
    
    // 返回凸包的面积,p 必须全部是凸包上的点
    double ConvexPolygonArea(Point * Polygon , int n)
    {
        double area = 0;
        for(int i = 1 ; i < n - 1 ; ++ i) area += Cross(Polygon[i]-Polygon[0],Polygon[i+1]-Polygon[0]);
        return area / 2.0;
    }
    
    // 复杂度 O(n)
    // 点在多边形内的判断
    int PointInPolygon(const Point & p,const Point * Polygon,const int n)
    {
        int wn = 0;
        for(int i = 0 ; i < n ; ++ i)
        {
            int t1 = i;
            int t2 = (i+1) >= n ? i+1-n : i+1;
            if (IsPointOnSegment(p,Polygon[t1],Polygon[t2])) return -1; // 点在多边形边界上
            int k = dcmp(Cross(Polygon[t2] - Polygon[t1],p - Polygon[t1]));
            int d1 = dcmp(Polygon[t1].y - p.y);
            int d2 = dcmp(Polygon[t2].y - Polygon[t1].y);
            if (k > 0 && d1 <= 0 && d2 > 0) wn ++;
            if (k < 0 && d2 <= 0 && d1 > 0) wn --;
        }
        if (wn != 0) return 1; //在多边形内部
        return 0; // 外部
    }
    
    //**********************************************************************************************
    
    // 计算凸包
    // 输入的p数组不允许有重复点
    // 如果不希望在凸包的边上有输入点,把两个<= 该成 <
    // 精度要求较高时用dcmp
    int ConvexHull(Point * p , int n , Point * ch)
    {
        sort(p,p+n,cmp1);
        int m = 0;
        for(int i = 0 ; i < n ; ++ i)
        {
            while(m > 1 && Cross(ch[m-1] - ch[m-2] , p[i] - ch[m-2]) <= 0 ) m --;
            ch[m++] = p[i];
        }
        int k = m;
        for(int i = n - 2 ; i >= 0 ; -- i)
        {
            while(m > k && Cross(ch[m-1] - ch[m-2] , p[i] - ch[m-2]) <= 0 ) m --;
            ch[m++] = p[i];
        }
        if (n > 1) m--;
        return m;
    }
    
    const int maxn = 2e2 + 50;
    int n , k ,cot;
    Point p[maxn];
    long long pos[maxn];
    
    int main(int argc,char *argv[])
    {
        double ans = 1e200;
        scanf("%d%d",&n,&k);
        if (n == 1)
        {
            printf("0
    ");
            return 0;
        }
        for(int i = 0 ; i < n ; ++ i) scanf("%I64d%I64d",&p[i].x,&p[i].y);
        for(int i = 0 ; i < n ; ++ i)
         for(int j = 0; j < n ; ++ j)
         {
         //    if (i == j) continue;
             long long dx = p[j].y - p[i].y;
             long long dy = p[i].x - p[j].x;
             long long c = dx * p[i].x + dy * p[i].y;
             int cur = 0;
             for(int kk = 0 ; kk < n ; ++ kk)
             {
                 long long d = dx * p[kk].x + dy*p[kk].y;
                 if (d - c >= 0)
                 {
                     pos[cur++] = d-c;
                 }
             }
             if (cur >= k)
             {
                 sort(pos,pos+cur);
                 ans = min(ans , (double)pos[k-1] / sqrt(dx*dx + dy*dy));
             }
         }
        if (dcmp(ans-1.00) <= 0) ans = 0.0;
        else ans -= 1.00;
        printf("%.10lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    BibTex (.bib) 文件的凝视
    SQL注入原理解说,非常不错!
    怎样将文件隐藏在图片中
    白话经典算法系列之五 归并排序的实现
    帮你理解多线程
    很好的理解遗传算法的样例
    薏米红豆粥功效及做法介绍
    Linux makefile 教程 很具体,且易懂
    站点权重对于站点的重要性
    Codeforces Round #250 (Div. 2)——The Child and Set
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4728580.html
Copyright © 2011-2022 走看看