うーん、割と苦戦。
https://yukicoder.me/problems/no/595
問題
N個の山が順に並んでおり、各高さはH[i]である。
今1番の山におり、全山を最低1回到達した状態にしたい。最後どの山で終えても構わない。
山の間は以下の通り移動が可能である。
- 隣接する山に移動する。移動先の山の方が高い場合、高さの差分だけコストがかかる。
- 任意の山にワープする。固定コストPがかかる。
解法
各山の到達方法は
- 左の山からくる
- 右の山からくる
- ワープしてくる
のいずれかである。
これを考慮しつつ、1手先読みを行うDPで山の状態遷移をさせていこう。
状態は以下の3つとする。
- 次に右に移動してもよい。上2つは次に移動する場所に関する状態だが、3つ目はどこから来るかに関する状態でちょっと異なるのに注意。
- 次に左に行くことが決まっている。
- 右から来られることを期待する。
左の山から状態別にDPし、コスト最小値を求めていく。
- この状態になるには、左の山から移動してくるか、ワープしてくる必要がある。
- この状態になるには、ワープしてくるか、次右から来られることを期待する必要がある。
- この状態は、どの状態からでも遷移できる。
int N; ll P,H[202020]; ll dp[3][202020]; void solve() { int i,j,k,l,r,x,y; string s; cin>>N>>P; FOR(i,N) cin>>H[i]; dp[0][0]=dp[1][0]=dp[2][0]=0; // 0-free 1-non 2-req for(i=1;i<N;i++) { dp[0][i]=min(dp[0][i-1]+min(P,max(0LL,H[i]-H[i-1])), dp[1][i-1]+P); dp[1][i]=dp[2][i-1]+P+min(P,max(0LL,H[i-1]-H[i])); dp[2][i]=min({dp[0][i-1],dp[1][i-1],dp[2][i-1]+min(P,max(0LL,H[i-1]-H[i]))}); } cout<<min({dp[0][N-1],dp[1][N-1]})<<endl; }
まとめ
誤解法でWAを繰り返してしまった。