Official
I - 魚釣り / PAST to Fishing Editorial by tatyam
以下の動的計画法を行います。
\(dp[i][j][k] = {}\)( 区画 \((i, j)\) までに \(k\) 匹魚を釣るときのおいしさの合計の最大値 )
漸化式は以下のようになります。
\[ \begin{aligned} dp[i][j][k] = \max(&dp[i-1][j][k],\\ &dp[i][j-1][k],\\ &dp[i-1][j][k-1] + A_{i,j},\\ &dp[i][j-1][k-1] + A_{i,j}) \end{aligned} \]
状態数が \(O(HW(H+W))\) 、遷移が \(O(1)\) なので、時間計算量は \(O(HW(H+W))\) です。
回答例 (C++)
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
void chmax(ll& a, ll b){ if(a < b) a = b; }
int main(){
ll H, W;
cin >> H >> W;
vector A(H, vector<ll>(W));
for(auto& a : A) for(ll& i : a) cin >> i;
const ll K = H + W - 1;
vector dp(H, vector(W, vector<ll>(K + 1)));
for(ll i = 0; i < H; i++){
for(ll j = 0; j < W; j++){
if(i) for(ll k = 0; k <= K; k++) chmax(dp[i][j][k], dp[i - 1][j][k]);
if(j) for(ll k = 0; k <= K; k++) chmax(dp[i][j][k], dp[i][j - 1][k]);
for(ll k = K; k--; ) chmax(dp[i][j][k + 1], dp[i][j][k] + A[i][j]);
}
}
for(ll k = 1; k <= K; k++) cout << dp.back().back()[k] << ' ';
}
回答例 (Python)
H, W = map(int, input().split())
A = [list(map(int, input().split())) for i in range(H)]
K = H + W - 1
dp = [[[]] * W] * H
for i in range(H):
for j in range(W):
if i and j:
a = [max(x, y) for x, y in zip(dp[i - 1][j], dp[i][j - 1])]
elif i:
a = dp[i - 1][j][:]
elif j:
a = dp[i][j - 1][:]
else:
a = [0] * (K + 1)
x = A[i][j]
for k in reversed(range(K)):
if a[k + 1] < a[k] + x:
a[k + 1] = a[k] + x
dp[i][j] = a
print(*dp[-1][-1][1:])
posted:
last update: