Official
D - アルバイトの計画 / Part-Time Job Planning Editorial
by
D - アルバイトの計画 / Part-Time Job Planning Editorial
by
physics0523
Editorial for printing
動的計画法 (DP) を用いてこの問題を解くことができます。
\(dp[i][j]=\{\) \(i\) 日目までバイトするかどうかを決定して、それまでに \(j\) 回バイトをした場合の給料の最大値 \(\}\) という形の DP を行います。
\(dp[i][j]\) からの遷移は次の通りです。
- \(dp[i+1][j]\) に \(dp[i][j]\) を遷移する。
- \(i+1\) 日目にバイトをしない場合に該当します。
- \(dp[i+D+1][j]\) に \(dp[i][j]+A_i\) を遷移する。
- \(i+1\) 日目にバイトをして、その後 \(D\) 日間はバイトができない場合に該当します。
本解法の時間計算量は \(O(NK)\) です。
実装例 (C++):
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main(){
ll N,K,D;
cin >> N >> K >> D;
vector<ll> A(N);
for(auto &nx : A){cin >> nx;}
vector<vector<ll>> dp(N+1,vector<ll>(K+1,-1e18));
dp[0][0]=0;
for(ll i=0;i<N;i++){
for(ll j=0;j<K;j++){
dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
dp[min(N,i+D+1)][j+1]=max(dp[min(N,i+D+1)][j+1],dp[i][j]+A[i]);
}
}
ll res=0;
for(auto &nx : dp){
res=max(res,(*max_element(nx.begin(),nx.end())));
}
cout << res << "\n";
return 0;
}
posted:
last update:
