經典物理建模題:球從 100m 高度落下,每次觸地反彈至原高度一半。求**第 10 次落地時總路程**與**第 10 次反彈高度**。
#include <stdio.h>
int main() {
double height = 100.0; // 初始高度
double total_distance = 0.0;
double rebound = height / 2.0; // 第一次反彈高度
// 第 1 次落地:只下落 100m
// 第 2~10 次落地:每次經歷「上升 + 下落」= 2 × 反彈高度
for (int i = 1; i < 10; i++) { // i=1~9 對應第 2~10 次落地前的反彈
total_distance += 2 * rebound;
rebound /= 2.0; // 下一次反彈高度減半
}
total_distance += height; // 加上第一次下落 100m
printf("第 10 次落地總路程 = %.6f 米\n", total_distance); // 299.609375
printf("第 10 次反彈高度 = %.6f 米\n", rebound); // 0.097656
return 0;
}
第 10 次落地總路程 = 299.609375 米 第 10 次反彈高度 = 0.097656 米
| 階段 | 動作 | 路程增量 | 累計路程 | 當前反彈高度 |
|---|---|---|---|---|
| 開始 | 靜止 100m | 0 | 0 | 100 |
| 第1次落地 | 下落 100m | +100 | 100 | 50 |
| 第1次反彈 | 上升 50m | +50 | 150 | 50 |
| 第2次落地 | 下落 50m | +50 | 200 | 25 |
| 第2次反彈 | 上升 25m | +25 | 225 | 25 |
| ... | ... | ... | ... | ... |
| 第9次反彈 | 上升 0.1953125m | +0.1953125 | 299.4140625 | 0.1953125 |
| 第10次落地 | 下落 0.1953125m | +0.1953125 | 299.609375 | 0.09765625 |
總路程 = 初始下落 + 2 × (首次反彈 + 二次反彈 + ... + 第9次反彈)
S = h + 2 × (h/2 + h/4 + ... + h/2⁹) = h + 2 × h/2 × (1 - (1/2)⁹) / (1 - 1/2) // 等比數列求和 = h + 2h × (1 - 1/512) = 100 + 200 × 511/512 = 100 + 199.609375 = 299.609375 ✓
第 10 次反彈高度 = h / 2¹⁰ = 100 / 1024 = 0.09765625 ✓
常見邏輯錯誤避坑
| 錯誤邏輯 | 後果 | 修正 |
|---|---|---|
| 迴圈 10 次全按 2×refund 計算 | 多加一次上升路程 | 第一次只有下落,迴圈跑 9 次 |
| 忘記加初始 100m | 少算 100m | 循環外加 `height` |
| 反彈高度更新順序錯誤 | 高度錯位 | 先累加路徑,再 `rebound /= 2` |
自由落體反彈問題核心在於**識別第一次落地只有下落**,後續每次落地皆含「上升+下落」。迴圈次數 = 落地次數 - 1。數學上為等比數列求和,程式上用累加器模擬更直觀。結果:**第 10 次落地總路程 299.609375 米,第 10 次反彈高度 0.097656 米**。