タイトルの意味を求めることは実質的に単調増加または単調最小コストを下げる変更シーケンスであり、コストは変化の絶対値を変更するフロントの高さとの差です。そして、DPと直接それを行います。我々は、DP [I] [J]私は高さをh [j]は最小コストで整然とした、段落を維持するための前部を表します。私たちがどのように変化するかに関係なくので、明らかに小さいフラッシュでその左右両側を変更する必要があります値を変更するため、実際には、変更の高さは常に、元のシーケンスの間で発生します。だから我々は非常に離散配列hを取得します。明らかに、その後伝達方程式は次のようになります。
DP [I] [J] =分(DP [I] [K])+ ABS([I] - H [J])。
そして、私たちは暴力を向けた場合には、N-の複雑さkの全てを列挙3を、明らかに爆発します。最適化を考えてみましょう。実際には、我々はKを列挙する必要はありません、とき最小DP直接前の転送[i]の[k]を決定することができ、コードの詳細は、以下を参照してください。
書式#include <cstdioを> する#include <iostreamの> の#include <cmath> の#include <CStringの> の#include < 文字列 > の#include <アルゴリズム> 書式#include <cstdlib> 書式#include <ctimeの> の#include <キュー> の#include <スタック> #include <ベクトル> の#include < 設定 > の#include <地図> の#include <両端キュー> の#defineは長い長いちゃう の#define N 2010 使って 名前空間STDを、 int型nは、CNT; DP [N] [N]。 INT [N]、H [N]。 INT メイン() { scanf関数(" %のD "、&N) 以下のために(int型 i = 1 ; iが<= N; iが++ ) { scanf関数(" %dを"&[I])。 H [I] = [I]。 } ソート(H + 1、H + N + 1 )。 int型 ANS = 100000000 ; 用(int型 iは= 1 iが<= N; iが++ ) { について(INT J = 1。 ; J <= N; J ++ ) { IF(Jの== 1)DP [I] [J]がDPを= [I - 1 ] [J] + ABS([I] - H [ J]); // 設定DP [I] [1]最小化される 他の DP [I] [J] =分(DP [I]、[J - 1 ]、DP [I - 1 ] [J] + ABS( A [I] - H [J])); // このステップは最小DP [I]、[J]を決定することである IF(== N-I)ANS =分(DP [I]、[J]、ANS)。// 最終タリー回答 } } のprintf(" %dの" 、ANS); 戻り 0 ; }