効果:$ N×m個の$ボード、$(1,1)$の横軸の初期位置は、$ \ FRAC {M + 1} {2} $することができ、ダウンしそうでないだけ回る、すべてのステップを取ることです$ 1 $秒$ T_I $時間ドリンクを過ごすために、$ k個の$管ミルク、$ I $タンクの位置$(R_iと、C_I)$を持っている。すべての$ 1 \ルI \ルのk $のために、ドリンクを取得牛乳で終わる$ I $最短チューブ。
書いた公式の説明によると、少し複雑$ DPの$のタイトルを達成。
主なアイデアは、各行左/右の$ X $ドリンクミルク缶の最小値に対して計算されると、その後、DP $合併答えを$。
#include <iostreamの> する#include <アルゴリズム> の#include <cstdioを> する#include <キュー> の#define REP(I、N)(iは= int型、iが<= N; I ++)のため の#define PER( I、N)(I = N int型のために、I> = A; - I) の#define X最初 の#define yの第二 の#define PBの一back 名前空間stdを使用。 typedefの長い長いLL。 typedefのペア<int型、int型> PII。 constのLL INF = 1E15; CONST int型N = 1E4 + 10。 N INT、M、K、B [N]。 構造体{int型のX、Y、T;} [N]。 LL ANS [N]。 ベクター<PII> V [N]。 ベクター<LL>解く(ベクトル<PII> A、INT S、INT X){ a.insert(a.begin()、PII(S、0)); ベクター<LL> RET(a.size()、INF)、T(RET)。 RET [0] = X == - 1 0:ABS(XS);? (I 1 = int型、iが(a.sizeを<); ++ i)について{ INT LEN = ABS([I] .xa [I-1] .X)。 REP(j、0、I-1)T [J] + = LEN。 PER(j、1、i)をT [J] =分(T [J]、T [J-1] + [I] .Y)。 REP(j、1、i)をRET [J] =分(RET [J]、T [J] +(X == - 1 0:ABS(XA [I] .X)))。 } RETを返します。 } ベクトル<LL>マージ(constのベクトル<LL>&L、constのベクトル<LL>&R){ ベクトル<LL> RET(L.size()+ R.size() - 1、INF)。 {(; iがL.sizeを()<++ iはi = 0 INT)のために (INT J = 0; J <R.size(); ++ j)のための{ RET分(RET = [iがjで+] )L [I] + R [J]、[私はjは+]。 } } 戻りRET。 } ボイドワーク(){ scanf関数( "%D%D%D"、&N、&M、およびK); * B = 0。 REP(I、1、K){ scanf関数( "%D%D%D"、& B [++ * B] = [I] .X。 } B [++ * B] = 1。 ソート(B + 1、B + 1 + * B)、* B =一意(B + 1、B + 1 + * B)-b-1。 REP(I、1、* B)V [I] .clear(); REP(I、1、K){ [I] .X = LOWER_BOUND(B + 1、B + 1件の+ * B、[I] .X)-b。 V [i]は.X] .pb(PII([I]・Y [i]が.T))。 ANS [I] = INF。 } REP(I、1、* B)ソート((V [i])と、端部(V [i])と開始)。 オートG =(V [1]、1、-1)を解きます。 (I 0 = int型、iが(g.sizeを<); ++ i)について{ ANS [I] =分(ANS [I]、G [I])。 } INT CUR = 0。 ベクター<LL> F [2]。 F [0] =(V [1]、1、(M + 1)/ 2)を解きます。 REP(I、2、* B){ CUR ^ = 1; オートP = LOWER_BOUND((V [i])と、端部(V [i])と、PII((M + 1)/ 2,0)を開始します)。 ベクター<PII> L、R(P、終了(V [I]))((V [i])と、P始めます)。 (L)、終了(L)(開始)逆。 自動f0は=(L、(M + 1)/ 2、(M + 1)/ 2)を解決するため、F1 =(R、(M + 1)/ 2、(M + 1)/ 2)を解きます。 オートG0 =(R、(M + 1)/ 2、-1)解く=(L、(M + 1)/ 2、-1)、G1を解決します。 G0 =マージ(F1、G0)、G1 =マージ(F0、G1)。 オートG = G0。 (INT J = 0; J <g.size(); ++ j)のための{ G [J] =分(G [J]、G1 [J])。 } G =マージ([!CUR]のF、G)。 F [CUR] =((F0、F1)をマージで、f [CUR!])マージ。 (INT J = 0; J <g.size(); ++ j)のための{ ANS [J] =分(ANS [J]、G [J] + B [I] -b [I-1])。 F [CUR] [J] + = B [I] -b [I-1]; } } REP(I、1、K){ IF(I == K)のprintf( "%LLDを\ n"、ANS [I])。 他のprintf( "%のLLD"、ANS [I]); } } int型のmain(){ 一方、(t--)ワーク(); int型のT。 scanf関数( "%のD"、&T)。 }