トピックリンク:http://acm.hdu.edu.cn/showproblem.php?pid=4261
問題の説明
「あまりにも多くの数字があります!」あなたの上司の轟音。「どのように私はこれらすべてを理解する必要があります?!見積りダウンそれを入れて!」
あなたが失望されています。これらの数字は、多くの作業を生成する必要があります。ただし、所有者の要件に合わせてそれを行います。
あなたは、以下の方法で推定することが決定:あなたはデジタル配列持ち A.を あなたはに分割されます kの 連続した部分、その大きさは必ずしも同じではありません。その後、あなたはセクション全体を推定するために番号を使用します。換言すれば、サイズ のnの 配列 A あなたはサイズの別の作成することが、 N個の アレイ B 有し、 k個 の連続する部分を。同じiとjの一部ならば、 B [I] = B [J]。(あなたは絶対差の和として表され、エラーを最小限にしたい [シグマ | A [I] -B [I] |)。
あなたが失望されています。これらの数字は、多くの作業を生成する必要があります。ただし、所有者の要件に合わせてそれを行います。
あなたは、以下の方法で推定することが決定:あなたはデジタル配列持ち A.を あなたはに分割されます kの 連続した部分、その大きさは必ずしも同じではありません。その後、あなたはセクション全体を推定するために番号を使用します。換言すれば、サイズ のnの 配列 A あなたはサイズの別の作成することが、 N個の アレイ B 有し、 k個 の連続する部分を。同じiとjの一部ならば、 B [I] = B [J]。(あなたは絶対差の和として表され、エラーを最小限にしたい [シグマ | A [I] -B [I] |)。
エントリー
入力のいくつかのテストケース。各テストケースは、ラインに二つの整数で始まる
Ñ
(1≦
Ñ
≤2,000)及び
K
(1≦
K
≦25、
K
≤
Ñ
)、
Nは
アレイの大きさであり、
kは
連続番号であります一部を推定します。配列
A
次回
のn
行、各行整数。
Aは
-10000(含む)〜10,000の整数要素の範囲。入力は2ゼロで終了します。
出力
各テストケースについては、あなたが達成できることを最小の誤差があり、独自のライン出力整数、上。出力されていない余分なスペースを行い、空白行は、あなたの答えを区切る使用しないでください。回答を生成するすべての可能な入力が、答えは64ビット符号付き整数に適しているであろう
サンプル入力
7 2
6
5
4
3
2
1
7
0 0
サンプル出力
9
(|愛のBi |)最小Kの部分に、Aの配列を与えられ、各部分は、1つが与えられ、B、例えばシグマのすべてのこと:問題の意味
ソリューションの概要:まず、状態DP [i]の[j]を定義します。i番目の分割ブロックjの最小コストの前に。[J] =分(DP [M] [I-1] + iは考慮Aに分割された(M + 1))[I] DP得ることは容易です。重要な問題は、その後、片にコストの範囲のすべてを得ることが可能となります。各間隔のために、考えることは容易である:ブロックAに対応し、この配列割当ブロックBは、配列の中央値は、この時点で最小のコストです。中央値を検索する方法についてように、2つのプライオリティキュー、優先度の大きな値を定義することができ、優先度の値が小さく、その2つのキュー、最初のチームの二つのセクションの中央値に各区間平均その後、1、およびそれにその価格帯を見つけます。
#include <ビット/ STDC ++ H> 名前空間STDを使用して、 const int型MAXN = 2E3 + 5。 INT DP [MAXN] [30]。 int型TEM [MAXN] [MAXN]。 [MAXN] int型。 const int型INF = 0x3f3f3f3f。 PRIORITY_QUEUE <int型、ベクトル<整数>、大きい<整数>> QUE1。 PRIORITY_QUEUE <整数> que2。 INT()は、メイン{ INT N、K。 一方、(!のscanf( "%D%D"、&N&K)= EOF){ IF(N == 0 && K == 0){ 戻り0; } ため(INT iは= 0; I <= N; I ++){ ため(INT J = 1; J <= K; J ++){ DP [I] [J] = INF。 } DP [i]は[I] = 0; } {(; <I = N I ++ iは1 = INT)のため のscanf( "%dの"、および[I])。 } (INT iについて1 =; I <= N。 (!que2.empty()))(que2.pop中。 int型SUM1、SUM2。 SUM1 = SUM2 = 0。 (; J> = 1; INT J = J - )は{ int型L1 =(I-J + 2)/ 2。 INT L2 =(I-J + 1)/ 2。 INT T = A [J]。 IF(que1.empty()){ SUM1 + = T。 que1.push(T)。 } 他{ もし(T> que1.top()){ SUM1 + = t-que1.top()。 que1.push(T)。 T = que1.top()。 que1.pop(); } IF(!que2.empty()&& T <que2.top()){ SUM2 + = t-que2.top()。 que2.push(T)。 T = que2.top()。 que2.pop(); } IF(que1.size()<L1){ SUM1 + = T。 que1.push(T)。 } 他{ SUM2 + = T。 que2.push(T)。 } } 、T = que1.top()。 INT T1 = -1。 (!que2.empty())の場合 、T1 = que2.top(); IF((I-J + 1)&1){ TEM [j]は[I] = SUM1-T * L1 + T * L2-SUM2。 } 他{ TEM [j]は[I] =分(SUM1-T * L1 + T * L2-SUM2、SUM1-T1 * L1 + T1 * L2-SUM2)。 } } } のために(INT I 1 =; I <= N; I ++){ DP [I] [1] = TEM [1]〜[I]。 } (INT iは2 = I ++; I <= k)に対する{ ための(int型J = I; J <= nであり、j ++){ ため(INT m = 1であり; M <Jであり; m ++){ DP [J] [ I] =分(DP [j] [i]は、DP [m]は[I-1] + TEM [M + 1]〜[J])。 } } } のprintf( "%D \ n"は、DP [n]が[K])。 } 0を返します。 }