CodeJam挑战题:求解用网球拍击中苍蝇的概率
嘿,咱们先把问题拆解清楚:概率本质就是弦条带覆盖的圆环区域面积 ÷ 整个圆环的面积。下面一步步来算:
1. 先算圆环的总面积
这个是基础,外半径R,内半径R-t,所以:
圆环总面积 = πR² - π(R-t)² = π(2Rt - t²)
公式很直观,外圆面积减去内圆面积即可。
2. 计算水平方向条带的总覆盖面积
水平条带的轴线是水平直线(外圆的弦),每个条带是距离轴线不超过r的区域(宽度2r),相邻条带的边缘间隙是g,所以两条相邻轴线的距离是 2r + g(条带宽度+间隙)。
2.1 确定水平条带的数量和位置
水平轴线的y坐标范围是从 -(R - r) 到 R - r——因为条带的边缘不能超出外圆,所以轴线距离外圆边缘至少r。对称分布的话,中间一根轴线在y=0处,其余上下对称排列。
假设总共有n_h根水平条带,计算方式为:
n_h = floor(2(R - r)/(2r + g)) + 1
如果2(R-r)能被(2r+g)整除,就是刚好的数量;否则向下取整后加1。每根条带的轴线y坐标为:k_i = -(R - r) + i*(2r + g),其中i从0到n_h-1。
2.2 单根水平条带在圆环内的覆盖面积
对于轴线为y=k的水平条带,它在圆环内的面积等于外圆内y∈[k-r, k+r]的区域面积减去内圆内y∈[k-r, k+r]的区域面积。
用几何积分公式计算:
- 外圆在y∈[a,b]的面积:
注意边界情况:如果a ≤ -R,就把a换成-R;如果b ≥ R,就把b换成R;如果a ≤ -R且b ≥ R,那就是整个外圆面积πR²。A_outer(a,b) = R²[arcsin(b/R) - arcsin(a/R)] + b√(R² - b²) - a√(R² - a²) - 内圆在y∈[a,b]的面积,把上面公式里的R换成R-t即可,记为
A_inner(a,b)。
所以单根水平条带的覆盖面积:
A_h(k) = A_outer(k-r, k+r) - A_inner(k-r, k+r)
2.3 所有水平条带的总覆盖面积
把每根水平条带的A_h(k)加起来就是:
S_h = Σ A_h(k_i) ,i从0到n_h-1
3. 垂直方向条带的总覆盖面积
因为垂直条带和水平条带完全对称,所以垂直条带的总覆盖面积S_v = S_h。
4. 计算水平与垂直条带的交叉重叠面积
这里要注意:水平和垂直条带的交叉区域被重复计算了一次(在S_h和S_v里各算一次),所以需要减去这部分的总面积。
对于每一对水平条带(轴线y=k)和垂直条带(轴线x=m),它们的交叉区域是一个边长为2r的正方形(或正方形与圆环的交集),满足|x - m| ≤ r且|y - k| ≤ r,同时在圆环内。
这个交叉区域的面积A_c(k,m)需要分情况计算:
- 如果整个正方形都在圆环内:面积就是
(2r)²=4r²。 - 如果正方形部分在外圆或内圆外:计算正方形在外圆内的部分面积,减去正方形在内圆内的部分面积。
所有交叉区域的总面积就是:
S_c = Σ Σ A_c(k_i, m_j) ,i从0到n_h-1,j从0到n_v-1
其中n_v是垂直条带的数量,和n_h相等。
5. 最终计算击中概率
总覆盖面积是水平加垂直减去重叠部分:
S_total = S_h + S_v - S_c = 2S_h - S_c
所以击中概率:
P = S_total / 圆环总面积 = (2S_h - S_c) / [π(2Rt - t²)]
特殊情况简化
如果r和g都远小于R和t,条带数量很多,可以近似计算:
单方向的覆盖占比约为2r/(2r+g),考虑交叉重叠后,总覆盖占比近似为:
(2r/(2r+g))*(2 - 2r/(2r+g))
此时概率就近似等于这个值(因为圆环区域均匀),这个简化只在条带非常密集时成立。
内容的提问来源于stack exchange,提问作者Perplexabot

