在网格上放置炸弹,如何用最少的炸弹覆盖最多的区域?🤔 这是函数优化问题
在 8×8 的网格上放置炸弹,炸弹会覆盖自身和上下左右相邻的格子。目标:用最少的炸弹覆盖所有格子。
先点「▶ 开始放置」,再切换策略。⚠️ 注意看覆盖率曲线的变化——是不是越来越平缓?
| 步骤 | 位置 | 新增覆盖 |
|---|
刚才的布雷游戏中,我们试图用最少的炸弹覆盖最多的格子。你发现了什么?
人教版必修第一册(P77):
设函数 f(x) 的输入的范围(x的取值范围)为 I,如果存在实数 M 满足:
① ∀x ∈ I,都有 f(x) ≤ M
② ∃x₀ ∈ I,使得 f(x₀) = M
那么 M 叫做函数 f(x) 的最大值。
类似地,满足 f(x) ≥ m 且 f(x₀) = m 的 m 叫做函数 f(x) 的最小值。
• 最大值 = 函数图象的「最高点」
• 最小值 = 函数图象的「最低点」
在函数应用中,二次函数的最值是最经典的问题:
在布雷问题中,覆盖率函数可以近似为二次函数: 开始时快速增长,后来增速放缓,最终趋于 100%。
对于更复杂的函数,我们可以用导数来求最值:
在炸弹人游戏中,导数 = 0 的点就是「再多放一个炸弹,新增覆盖几乎为 0」的位置——这就是最优解!
在二次函数 y = ax² + bx + c 中,调节参数 a、b、c,观察图象的开口方向、对称轴和最值位置。
把 a 调到 -1、b 调到 0,得到 y = -x² + c,这是一个关于 x=0 对称的抛物线,最大值在顶点处——就像炸弹放在正中心覆盖最多!
def quadratic_extreme(a, b, c): """求二次函数 y=ax²+bx+c 的最值""" x_vertex = -b / (2 * a) y_vertex = a * x_vertex**2 + b * x_vertex + c if a > 0: return f'最小值: y={y_vertex:.2f} (x={x_vertex:.2f})' return f'最大值: y={y_vertex:.2f} (x={x_vertex:.2f})' # 例:y = -x² + 4x + 1 print(quadratic_extreme(-1, 4, 1)) # 最大值: y=5.00 (x=2.00) # 例:y = x² - 6x + 5 print(quadratic_extreme(1, -6, 5)) # 最小值: y=-4.00 (x=3.00)
最大值: y=5.00 (x=2.00) 最小值: y=-4.00 (x=3.00)
from scipy.optimize import minimize_scalar # 覆盖率函数 f(x) = 1 - e^(-0.3x) def coverage(x): return -(1 - 2.71828**(-0.3*x)) # 负号因为求最小 result = minimize_scalar(coverage, bounds=(0, 20), method='bounded') print(f'最优炸弹数: {result.x:.1f}') print(f'最大覆盖率: {-result.fun*100:.1f}%')