在網格上放置炸彈,如何用最少的炸彈覆蓋最多的區域?🤔 這是函式最佳化問題
在 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}%')