F - Earn to Advance Editorial by evima
旅程の中で最後に金を稼ぐマスを \(X\) とします。このとき、\(X\) には可能な最小のターン数で辿り着くべきです(最適な旅程では \(X\) がそこまでで最も儲かるマスのはずで、途中でターンを犠牲にして小銭を稼ぐ意味はありません)。ただし、そのターン数で可能な最大の金額を持っていくべきです。
\(X\) までの道中についても同じことがいえます。このプロセスを動的計画法に変換することで、 \(O(N^4)\) 時間の解法が得られます。
実装例(Python)
N = int(input())
P = [list(map(int, input().split())) for _ in range(N)]
R = [list(map(int, input().split())) for _ in range(N)]
D = [list(map(int, input().split())) for _ in range(N - 1)]
INF = 10**18
dp = [[(INF, 0) for j in range(N)] for i in range(N)]
dp[0][0] = (0, 0)
for i in range(N):
for j in range(N):
dist = [[INF for x in range(j + 1)] for y in range(i + 1)]
dist[i][j] = 0
for y in range(i, -1, -1):
for x in range(j, -1, -1):
if y < i:
dist[y][x] = min(dist[y][x], D[y][x] + dist[y + 1][x])
if x < j:
dist[y][x] = min(dist[y][x], R[y][x] + dist[y][x + 1])
c = max(0, dist[y][x] - dp[y][x][1] + P[y][x] - 1) // P[y][x]
t = dp[y][x][0] + c + i - y + j - x
m = dp[y][x][1] + c * P[y][x] - dist[y][x]
if t < dp[i][j][0] or t == dp[i][j][0] and m > dp[i][j][1]:
dp[i][j] = (t, m)
print(dp[N - 1][N - 1][0])
posted:
last update: