Gameboy 站在 0~10 共 11 個位置的線上,初始位置 5。每秒只能移動 ≤1 格(左、右、原地)。第 t 秒位置 x 掉落餡餅(同一時刻同位置可多個)。求最多能接住多少個餡餅。n, t ≤ 100,000。
關鍵洞察:從最後一秒 逆向遞推 到第 0 秒。
dp[t][x] = 從第 t 秒位置 x 開始,到結束能接的最大餡餅數。
轉移:dp[t-1][x] = pie[t-1][x] + max(dp[t][x-1], dp[t][x], dp[t][x+1])
邊界:x=0 只能來自 x=0,1;x=10 只能來自 x=9,10。
答案:dp[0][5](初始位置 5,為方便下標從 1 開始,實際用 dp[0][6])。
dp[2][12] 兩行滾動,空間 O(1)。scanf 讀入,避免 cin 超時。#include#include #include using namespace std; int dp[2][12]; // 滾動數組:當前行、下一行 int pie[100001][12]; // pie[t][x] 第 t 秒位置 x 的餡餅數 int main() { int n; while (scanf("%d", &n) == 1 && n) { memset(pie, 0, sizeof(pie)); int Tmax = 0; for (int i = 0; i < n; ++i) { int x, t; scanf("%d%d", &x, &t); ++pie[t][x+1]; // 位置 0~10 → 下標 1~11 Tmax = max(Tmax, t); } // 逆向遞推:從 Tmax 遞推到 1 for (int t = Tmax; t >= 1; --t) { int cur = t & 1, nxt = cur ^ 1; for (int x = 1; x <= 11; ++x) { int best = dp[nxt][x]; if (x > 1) best = max(best, dp[nxt][x-1]); if (x < 11) best = max(best, dp[nxt][x+1]); dp[cur][x] = pie[t-1][x] + best; // 注意:pie 索引對齊 } } printf("%d\n", dp[1][6]); // 第 0 秒位置 5 → 下標 6 } return 0; }
++pie[t][x] 而非賦值。