poj 3122 Pie 二分

poj 3122 Pie 二分
//poj 3122 Pie
//二分

//题意:
//给出pie和人的数量,要把这些pie平均分给每个人

//思路:
//先用pie的半径r平方代替面积,到最后再乘上PI
//求出所有r^2的和,除以人数当做二分的high,low=0
//接着相当于对每个人得到的体积进行二分
//每一次二分要计算切出来的蛋糕数是否大于等于人数,若是
//则满足条件,否则不满足要缩小没人得到的体积

//注意:
//是限定每个人得到的体积后从每块pie切
//若某块pie最后剩的不足一个人份则剩的扔掉
//即如果一个pie体积为3,每个人分得体积为2
//则这个pie要人掉1体积,而不能和别的pie剩下的掺到一起
//即每一块蛋糕要来自同一块儿大蛋糕,因为这样看起来美观
//
//用%lf一只wa,用%f就能ac,不知道为什么···纠结了好久


#define infile freopen("in.txt", "r", stdin);
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;

const int INF = 1<<30;
const int N = 10050;
const double PI = acos(-1.0);
const double eps = 1e-8;

int n_pie, n_man;
double radii2[N];

bool is_ok(double mid)
{
    int cnt = 0;
    for(int i = n_pie-1; i >= 0; --i)
    {
       cnt += int(radii2[i] / mid);
       if(cnt >= n_man)
        return true;
    }
    return false;
}

double binarySearch(double high)
{
    double low = 0, ans;
    while(high - low >= eps)
    {
        double mid = low + (high-low)/2;
        if(is_ok(mid))
        {
            ans = mid;
            low = mid + 1e-5;
        }
        else
            high = mid - 1e-5;
    }
    return ans*PI;
}

int main()
{
    int n_case;
    scanf("%d", &n_case);
    while(n_case--)
    {
        scanf("%d%d", &n_pie, &n_man);
        n_man++;
        double sum = 0;
        for(int i = 0; i < n_pie; ++i)
        {
            int r;
            scanf("%d", &r);
            radii2[i] = double(r*r);
            sum += radii2[i];
        }
//        sort(radii2, radii2+n_pie);
//        double high = radii2[n_pie-1];
        //用 %.4lf 会错,不知为什么
        printf("%.4f\n", binarySearch(sum / n_man));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/gabo/p/2645397.html