D - Bonus EXP Editorial by mechanicalpenciI
この問題は動的計画法によって解くことができます。
「\(k\) 匹目までのモンスターと出会い、偶数(\(0\) を含む)匹倒した時に得られる経験値の最大値」と「\(k\) 匹目までのモンスターと出会い、奇数匹倒した時に得られる経験値の最大値」(そのようなことが不可能な場合は \(-\infty\) )をそれぞれ \(dp_{even}[k]\), \(dp_{odd}[k]\) とします。
最初、\(dp_{even}[0]=0\), \(dp_{odd}[0]=-\infty\) です。
ここで、\(1\leq i\leq N\) について、\(i\) 匹目のモンスターから得られる経験値は、
- 高橋君が逃がすと倒すのどちらを選択したか
- (倒すことを選択した際)それまでに倒したモンスターの数が偶数か奇数か
にのみ依存して決まることに注意します。さらに、「\(i\) 匹目までのモンスターと出会い、偶数匹倒す」パターンは以下のどちらかしかありません。
- \(k-1\) 匹目までの間に偶数匹倒し、\(k\) 匹目のモンスターを逃がした場合
- \(k-1\) 匹目までの間に奇数匹倒し、\(k\) 匹目のモンスターを倒した場合
よって、\(dp_{even}[i-1]\), \(dp_{odd}[i-1]\) の値が求まっている時、\(dp_{even}[i]\) は、
\[ dp_{even}[i]=\max(dp_{even}[i-1],dp_{odd}[i-1]+2A_i) \]
として求めることができます。同様に \(dp_{odd}[i]\) は、
\[ dp_{odd}[i]=\max(dp_{odd}[i-1],dp_{even}[i-1]+A_i) \]
として求めることができます。
最終的な答えは \(\max(dp_{even}[N],dp_{odd}[N])\) となります。
このときの計算量は \(O(N)\) であり、今回の制約下で十分高速です。
よってこの問題を解くことができました。
C++ による実装例:
#include <bits/stdc++.h>
using namespace std;
#define INF (long long)1e+18
int main(void){
int n;
long long x,dp0=0,dp1=-INF,tmp;
cin>>n;
for(int i=0;i<n;i++){
cin>>x;
tmp=dp0;
dp0=max(dp1+2*x,dp0);
dp1=max(tmp+x,dp1);
}
cout<<max(dp0,dp1)<<endl;
return 0;
}
posted:
last update: