算法实践:派 (二分)

蛋糕切分

描述

林克被造的纪念日快要到了。根据任天堂公司的惯例,每年到这个时间都会一些蛋糕分给林克的朋友。这些蛋糕有不同的口味,比如南瓜蛋糕、坚果蛋糕、西瓜蛋糕、胡萝卜蛋糕、水果蛋糕等等(有N种不同口味,大小不同的蛋糕)。
为了公平,每个朋友都会分到一块大小相同的蛋糕(不需要同样形状,但是要同一种口味,不允许混合口味,否则就会变成奇怪的菜肴)。
假设每个蛋糕都是一个高为1,半径不等的圆柱体,一共有F+1个人(F是林克的朋友个数,还要加上林克的设计者)。

所有人拿到的蛋糕是同样大小的,请问每个人拿到的蛋糕最大是多少?

输入

第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示蛋糕的数量和朋友的数量。

第二行包含N个1到10000之间的整数,表示每个蛋糕的半径。

输出

输出每个人能得到的最大的蛋糕的体积,精确到小数点后三位。

样例

3 3
4 3 3
25.133

难度

中等

解法

首先对蛋糕的大小进行排序,对没人能得到的最大蛋糕体积进行二分查找,查找区间为left = 最小蛋糕体积/该分的人数,right = 最大蛋糕体积。

Hasenoughcake函数用于判断蛋糕是否够分,如果不够分,right = mid, 如果够分,left = mid +eps 。eps为一个很小的数。

需要注意最后的输出格式和pi的精度。

代码

import math
# 输入
x = input()
x = x.split(' ')
N = (int)(x[0])
F = (int)(x[1])+1  #多一个设计者
y = input().split(' ')
cake = []
eps = 1e-6
for i in range(N):
    cake.append((int)(y[i])**2*math.pi)
cake.sort(reverse = True)

def hasenoughcake(size):
    if(size<eps):
        return True
    count = 0
    for i in range(len(cake)):
        if(cake[i]<size):
            continue
        elif(cake[i]>=size):
            pieces = (int)(cake[i]/size)
            count += pieces
    if(count>=F):
        return True
    else:
        return False

def binarySearch():
    left = cake[-1]/F
    right = cake[0]
    while(left<right):
        mid = (left+right)/2
        if(hasenoughcake(mid)):
            left = mid + eps
        else:
            right = mid
    return left

ans = binarySearch()
print("%.3lf"%ans)
发布了129 篇原创文章 · 获赞 148 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/matafeiyanll/article/details/104863513