Codeforces 242(DIV 2) B题

思路:有两种方法:(1)二分枚举答案,(2)排序,然后直接扫描,这里有个小技巧,就是每个节点都保存距离比它小的节点的人数之和,这样可以在降低第二步处理的时间复杂度,总是间复杂度为O(nlogn)+O(n) = O(nlogn)。两种方法运行时间一样,一开始我是直接二分的,做完后看题目标签是sort,然后感觉排序可做,就写了一下。

二分版:
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1010
using namespace std;
const double eps = 1e-8;
typedef struct Point{
    int x, y, man;
    double dist;
    void d(){
         dist = sqrt(x*x+y*y);
    }
}Point;
Point P[MAXN];
int n, s;
int Judge(double len){
    int sum = 0;
    for(int i = 0;i < n;i ++){
        if(P[i].dist + eps < len) sum += P[i].man;
        if(sum + s >= 1000000) return 1;
    }
    return -1;
}
double binary_Search(double l, double r){
    double ll, rr, mid;
    ll = l, rr = r;
    while(ll < rr+eps){
        mid = (ll + rr)/2;
        int flag = Judge(mid);
        if(flag == 1) rr = mid-eps;
        else if(flag == -1) ll = mid+eps;
    }
    return ll;
}
int main(){
    double maxn;
    /* freopen("in.c", "r", stdin); */
    /* freopen("out.cpp" , "w", stdout); */
    while(~scanf("%d%d", &n, &s)){
        int sum = 0;
        maxn = eps;
        for(int i = 0;i < n;i ++){
            scanf("%d%d%d", &P[i].x, &P[i].y, &P[i].man);
            P[i].d();
            sum += P[i].man;
            maxn = max(maxn, P[i].dist);
        }
        if(sum + s < 1000000) printf("-1\n");
        else if(sum + s == 1000000) printf("%.8lf\n", maxn);
        else printf("%.8lf\n", binary_Search(eps, maxn));
    }
    return 0;
}

sort版:
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1010
const double eps = 1e-8;
using namespace std;
typedef struct Point{
    int x, y, man, sum;
    double dist;
    void d(){
        dist = sqrt(x*x+y*y);
    }
    bool operator < (const Point &A) const{
        return dist < A.dist;
    }
}Point;
Point P[MAXN];
int main(){
    int n, s;
    /* freopen("in.c", "r", stdin); */
    while(~scanf("%d%d", &n, &s)){
        int sum = 0;
        double maxn = eps;
        for(int i = 0;i < n;i ++){
            scanf("%d%d%d", &P[i].x, &P[i].y, &P[i].man);
            P[i].d();
            maxn = max(maxn, P[i].dist);
            sum += P[i].man;
            P[i].sum = P[i].man;
        }
        if(sum + s < 1000000) printf("-1\n");
        else if(sum + s == 1000000) printf("%.8lf\n", maxn);
        else{
            sort(P, P+n);
            for(int i = 0;i < n;i ++){
                if(P[i].sum + s >= 1000000){
                    printf("%.8lf\n", P[i].dist);
                    break;
                }
                P[i+1].sum += P[i].sum;      //注意这点;
            }
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值