ACM-ICPC 2018 沈阳赛区网络预赛 E The cake is a lie

知乎上有这个问题 比赛的时候实现了算法 调了整场啊... 知乎链接

 

按照这位大佬的代码 取大于的所有区间终于过了 这里

然而我的把角度全部映射到-pi~pi的算法怎样也过不了

 

Node的排序方法也是玄学 不要优先+1反而ac 优先+1反而wa

总之就是把下面代码的注释全部去了差不多就是我的错误代码了。。求好心的大佬帮忙看一下。。

附上这个被改成长得跟别人差不多的ac代码。。。

#include <iostream>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <algorithm>
using namespace std;
const double eps=1e-6;
const double pi=acos(-1.0);
int sgn(double x)
{
    if(fabs(x)<eps)return 0;
    return x>eps?1:-1;
}
struct Point {
    double x, y;
    Point() {}
    Point(double _x, double _y) {
        x = _x;
        y = _y;
    }
    void input() {
        scanf("%lf%lf", &x, &y);
    }
    void output() {
        printf("%.2f %.2f\n", x, y);
    }
    bool operator==(Point b) const {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
    bool operator<(Point b) const {
        return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
    }
    Point operator-(const Point &b) const {
        return Point(x - b.x, y - b.y);
    }
    //叉积
    double operator^(const Point &b) const {
        return x * b.y - y * b.x;
    }
    //点积
    double operator*(const Point &b) const {
        return x * b.x + y * b.y;
    }
    double distance(Point p) {
        return hypot(x - p.x, y - p.y);
    }
    Point operator+(const Point &b) const {
        return Point(x + b.x, y + b.y);
    }
    Point operator*(const double &k) const {
        return Point(x * k, y * k);
    }
    Point operator/(const double &k) const {
        return Point(x / k, y / k);
    }
};
struct Node{
    int f;
    double a;
    Node(double _a,int _f){f=_f;a=_a;}
    Node(){}
    bool operator<(const Node&b)const{
//        if(sgn(a-b.a)==0)return f>b.f;
        return a<b.a;
    }
}g[10000];
double get(double x)
{
    while(sgn(x+pi)<0)x+=2*pi;
    while(sgn(x-pi)>0)x-=2*pi;
    return x;
}
void add(double a,double b,int &cnt)
{
//    a=get(a);
//    b=get(b);
    a+=2*pi;
    b+=2*pi;
    g[cnt]=Node(a,1);cnt++;
    g[cnt]=Node(b,-1);cnt++;
//    if(sgn(a-b)>0)
//    {
//        g[cnt]=Node(-pi,1);cnt++;
//        g[cnt]=Node(pi,-1);cnt++;
//    }
}
void fuck(Point p1,Point p2,int &cnt,double R)
{
    double d=p1.distance(p2);
    if(d>R*2)return;
//    if(sgn(d)==0)///重合
//    {
//        add(-pi,pi,cnt);
//    }
//    else if(sgn(d-R*2)==0)///相切
//    {
//        double t=acos((p2.x-p1.x)/d);
//        add(t,t,cnt);
//    }
//    else///相交
    {
        double A=acos(0.5*d/R);
//        double B=acos((p2-p1).x/d);
        double B=atan2((p2-p1).y,(p2-p1).x);
        if(B<0)B+=2*pi;
//        if(!flag)
//            add(B+A,B-A,cnt);
//        else
            add(B-A,B+A,cnt);
    }
}
Point p[100000];
int main()
{
    double R;
    int n,T,s,rr;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&s);
        for(int i=0;i<n;i++)
        {
            p[i].input();
        }
        R=0;
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                R=max(R,p[i].distance(p[j]));
            }
        }
        scanf("%d",&rr);
        if(s>n)
        {
            printf("The cake is a lie.\n");
            continue;
        }
        if(s==1)
        {
            printf("%d.0000\n",rr);
            continue;
        }
        double ri=R;
        double le=0;
        int mx;
        while(ri-le>eps)
        {
            mx=0;
            double mid=0.5*(le+ri);
            int flag=0;
            for(int i=0;i<n;i++)
            {
                int cnt=0;
                for(int j=0;j<n;j++)
                {
                    if(i==j)continue;
                    fuck(p[i],p[j],cnt,mid);
                }
                sort(g,g+cnt);
                int ss=1;
                for(int j=0;j<cnt;j++)
                {
                    ss+=g[j].f;
                    mx=max(ss,mx);
                    if(ss>=s)
                    {
                        flag=1;
                        break;
                    }
                }
                if(flag)break;
            }
            if(flag) ri=mid;
            else le=mid;
        }
        le+=rr;
        printf("%.4f\n",le);
    }
    return 0;
}
/*
2
3 3
0 0
1 1
2 0
1
3 3
0 0
1 1
2 2
1
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值