DFS + DP
私たちは小さな値のマトリックスように大行列で小行列を選出する必要が最小
だから我々は、行は最後に答えを更新し、その後、列が選択された行のDFSに基づいてDP、選挙を列挙DFSで始まります。
具体的には、我々は最初の行をrはDFSを列挙し、二つの配列を計算する:和[I] [j]を示し、I番目の列と状態の現在の行の隣接列jは値DFSを決定するときに生成されます。ステータス行にS [i]が選択された行rのi番目の列の後に値を決定し、現在のDFSを示します。
その後、Fで定義された我々の最初の列DPは、[I] [j]は、選択されたカラムiおよび列j(iは列選択をTH)スコア、状態遷移方程式の前に決定された現在のステータス行は、DFSを示し非常にシンプル。
だから我々はこの問題を解決する必要があります。
1の#include <iostreamの> 2の#include <cstdioを> 3の#include <CStringの> 4の#include <アルゴリズム> 5の#include <cmath> 6 使って 名前空間STD。 7 typedefの長い 長いLL。 8 int型N、M、R、C。 9インラインint型リード(){ 10 INT RET = 0 。 11 int型 OP = 1 。 12 チャー C = GETCHAR()。 13 一方、(C < ' 0 '|| C> ' 9 '){ もし、(C == ' - ')OP = - 1。C = GETCHAR();} 14 ながら(C <= ' 9 ' && C> = ' 0 ')RET = RET * 10 + C- ' 0 '、C = GETCHAR()。 15 リターンのRET *のオペアンプ。 16 } 17 INT [ 20 ] [ 20 ]、ANS = 999999999 。 18 のint F [ 20 ] [ 20]、今[ 20 ]、合計[ 20 ] [ 20 ]、S [ 20 ]。 19 ボイドCALC(){ 20 のmemset(S、0、はsizeof (S))。 21 のmemset(和、0、はsizeof (合計))。 22 のために(int型 I = 1 ; I <= M I ++ ) 23 のための(INT J = 2、J <= R; J ++ ) 24 - S [I] + = ABS([今[J] [I] [今[J- 1 ]] [I])。 25 のための(int型I = 1 ; I <= M; iが++ ) 26 のための(INT J = I + 1、J <= Mであり、j ++ ) 27 のための(INT K = 1 ; <= R kは、k個++ ) 28 和[I] [J] + = ABS([今[K] [I] - [今[K] [J])。 29 } 30 INT DP(){ 31 のint RET = 999999999 。 32 のmemset(F、0x3fを、はsizeof (F))。 33 のために(int型 I = 1 ; I <= M Iは++ ){ 34 F [i]を[ 1 ] =のS [i]は、 35 のために(INT J = 2、J <= C; J ++ ) 36 のための(INT K = 1 ; <I k個あり、k ++ ) 37 F [I] [J] =分([I]、[J]、F [F K] [J- 1 ] + S [I] + 和[K] [I])。 38 RET = (F [i]が[C] RET)分。 39 } 40 リターンRET。 41 } 42の 空隙 DFS(INT U){ 43 であれば(U == R + 1 ){ 44 CALC()。 45の ANS = 分(ANS、DP())。 46 リターン; 47 } 48 のための(int型 I =今[U- 1 ] + 1 ; iが<= N; iが++ ){ 49 今や[U] = Iと、 50の DFS(U + 1 )。 51は 今[U] = 0 ; 52 } 53 } 54 、INT (){主 55 N =(読み取り)M =読み取ります(); R =リード()。C = リード()。 56 のために(int型 i = 1 ; iが<= N; iが++ ) 57 のための(int型 J = 1 ; J <= Mであり、j ++ ) 58 [I] [J] = 読み取ります(); 59の DFS(1 )。 60 のprintf(" %d個の\ n " 、ANS)。 61 リターン 0 。 62 }