本文参考以下链接,如有侵权,联系删除
参考
题目描述
链接:https://www.nowcoder.com/questionTerminal/14c0359fb77a48319f0122ec175c9ada
来源:牛客网
有三种葡萄,每种分别有a,b,c颗。有三个人,第一个人只吃第1,2种葡萄,第二个人只吃第\2,3种葡萄,第三个人只吃第1,3种葡萄。
适当安排三个人使得吃完所有的葡萄,并且三个人中吃的最多的那个人吃得尽量少。
解析
先不管每个人只能吃两种特定葡萄的约束,你怎么让「吃得最多的那个人吃得最少」?
只要平均分就行了,每个人吃(a+b+c)/3颗葡萄。即便不能整除,比如说a+b+c=8,那也要尽可能平均分,就是说一个人吃 2 颗,另两个人吃 3 颗。
综上,「吃得最多的那个人吃得最少」就是让我们尽可能地平均分配,而吃的最多的那个人吃掉的葡萄颗数就是(a+b+c)/3
向上取整的结果,也就是(a+b+c+2)/3
。
PS:向上取整是一个常用的算法技巧。大部分编程语言中,如果你想计算M除以N,M / N会向下取整,你想向上取整的话,可以改成(M+(N-1)) / N
。
考虑一下如果加上「每个人只能吃特定两种葡萄」的限制,怎么做?
如果把葡萄的颗数a, b, c作为三条线段,它们的大小作为线段的长度,三个顶点看做三个人
假设a<b<c
如果a + b > c
,那么可以构成一个三角形,只要取每条边的中点,就一定可以把这个三角形的周长平分成三份,且每一份都包含两条边:
也就是说,这种情况下,三个人依然是可以平均分配所有葡萄的,吃的最多的人最少可以吃到的葡萄颗数依然是(a+b+c+2)/3
。
如果a + b <= c
,这三条边就不能组成一个封闭的图形了,那么我们可以将最长边c「折断」,也就是形成一个四边形。
这里面有两种情况:
- 对于情况一,a + b和c的差距还不大的时候,可以看到依然能够让三个人平分这个四边形,那么吃的最多的人最少可以吃到的葡萄颗数依然是
(a+b+c+2)/3
。 - 随着c的不断增大,就会出现情况二,此时
c > 2*(a+b)
,由于每个人口味的限制,其中一个人顶多吃完a和b,为了尽可能平分,c边需要被另外两个人平分,也就是说此时吃的最多的人最少可以吃到的葡萄颗数就是(c+1)/2
,即平分c边向上取整。
代码
def putao(a,b,c):
nums = [a,b,c]
nums.sort()
s = a + b + c
if nums[0] + nums[1] > nums[2]:
return (s + 2) // 3
if 2 * (nums[0] + nums[1]) < nums[2]:
return (nums[2] + 1) // 2
return (s + 2) // 3