ZOJ 3623 經典動態規劃問題:工廠生產戰艦攻擊防禦塔,每種戰艦有生產時間 tᵢ 和每秒傷害 lᵢ,求擊沉塔 (血量 L) 的最短時間。
tᵢ 秒,生產完成後每秒造成 lᵢ 傷害定義 dp[j] = 第 j 秒結束時能造成的最大總傷害。
若在第 j - tᵢ 秒開始生產第 i 種戰艦,則在 j 秒時:
j - tᵢ 秒最大傷害:dp[j - tᵢ]j - tᵢ + 1 到 j 秒工作:tᵢ 秒 × lᵢ 傷害/秒tᵢ 秒,故工作時間為 j - tᵢ 秒dp[j] = max(dp[j], dp[j - tᵢ] + (j - tᵢ) × lᵢ)
#include <stdio.h>
#include <string.h>
#define MAX_T 500 // 足夠大的時間上限
int dp[MAX_T];
int t[31], l[31];
int max(int a, int b) { return a > b ? a : b; }
int main() {
int n, L;
while (scanf("%d %d", &n, &L) != EOF) {
for (int i = 1; i <= n; ++i) {
scanf("%d %d", &t[i], &l[i]);
}
memset(dp, 0, sizeof(dp));
// 完全背包:外層遍歷物品,內層遍歷容量 (正序)
for (int i = 1; i <= n; ++i) {
for (int j = t[i]; j < MAX_T; ++j) {
dp[j] = max(dp[j], dp[j - t[i]] + (j - t[i]) * l[i]);
}
}
// 找最小時間
for (int j = 1; j < MAX_T; ++j) {
if (dp[j] >= L) {
printf("%d\n", j);
break;
}
}
}
return 0;
}
| 輸入 | 解析 | 輸出 |
|---|---|---|
| 1 1 1 1 | 1 種戰艦,t=1, l=1,塔血量 1 第 1 秒生產完成,第 2 秒造成 1 傷害 | 2 |
| 2 10 1 1 2 5 | 選擇第 2 種:t=2, l=5 第 2 秒生產完成,第 3、4 秒各 5 傷害 = 10 | 4 |
| 3 100 1 10 3 20 10 100 | 綜合最優策略 | 5 |
| 指標 | 複雜度 |
|---|---|
| 時間 | O(N × T_max) |
| 空間 | O(T_max) |
其中 T_max ≈ 500 為經驗上限 (L ≤ 330, lᵢ ≥ 1 → 最多 330 秒 + 生產時間)。
(j - tᵢ) 為實際工作秒數,非 j