タイトル
次の3つの能力を与える最初に水で満たされた唯一の最初の3杯、他の2つのカップの空の$カップC $、B、です。あなたは、少なくともどのくらいの水に$ Dの$ lのそれは持っている水のコップを作る必要がありますか?正確$ D $ Lをしないと、水のガラスは$ {D} $ dが$に近い<D $および '$ {D}の$ L' でありましょう。($ 1 \当量のA、B、C、Dの\の当量200 $)
分析
第1カップは、それから、状態$((v_0、V_1、V_2))$であると言って、水の第三のカップ$ V_2の$リットルあり、第2カップは、水の$ V_1 $リットルを有する水の$ v_0 $リットルを設定していますカップは、次の状態を注ぐ他のカップに向かって延長され、セットダウン水は、2つの状態間の距離です。ダイクストラと同様に、各キューは、それぞれの時間は、あなたの答えを更新し、最小距離から排出されることを保証することが可能です。
水の総量は変化しないので、それは$ v_0、V_1 $決定、$ V_2 $も決定されているので、状態の実際の数は$ 200 ^ 2 $です。
書式#include <cstdioを> する#include <CStringの> の#include <キュー> 使用して 名前空間はstdを、 構造体ノード{ int型 V [ 3 ]、DIST。 ブール 演算子 <(constのノード&RHS)のconst { 戻り DIST> rhs.dist。 } }。 const int型 MAXN = 200 + 5 。 int型のマークは[MAXN] [MAXN]、DIST [MAXN] [MAXN]、キャップ[ 3 ]、[MAXN] ANS。 ボイド update_ans(CONSTノード&U){ 用(int型 I = 0 ; iが< 3 ; iが++ ){ int型、D = UV [i]は、 もし(ANS [D] < 0 || u.dist <ANS [D])ANS [D] = u.dist。 } } ボイド(解決int型、int型 B、int型 C、int型の{d)を キャップ[ 0 ] =。キャップ[ 1 ] = B; キャップ[ 2 ] = C; memset(ANS、 - 1、はsizeof (ANS))。 memsetの(マーク、0、はsizeof (商標))。 memset(DIST、 - 1、はsizeof (DIST))。 PRIORITY_QUEUE <ノード> Q; ノード開始。 start.dist = 0 ; start.v [ 0 ] = 0。start.v [ 1 ] = 0。start.v [ 2 ] = Cと、 q.push(スタート)。 DIST [ 0 ] [ 0 ] = 0 。 一方、(!q.empty()){ ノードU = q.top()。q.pop(); もし(マーク[UV [ 0 ] [紫外線[ 1 ])続け; マーク[UV [ 0 ] [UV [ 1 ] = 1 。 update_ans(U)。 もし(ANS [D]> = 0)破ります。 以下のために(int型 i = 0 ; iは< 3 ; I ++ ) のための(INT J = 0 ; J < 3 ; J ++)場合(!I = J){ 場合(UV [I] == 0 || UV [J] = =キャップ[J])を続けます。 INTの量=分(キャップ[J]、UV [I] + UV [J]) - UV [J]。 ノードU2 = U; u2.dist = u.dist + 量。//换成+1、就是求最少次数 u2.v [i]は - = 量を、 u2.v [J] + = 量。 INT&D = DIST [u2.v [ 0 ] [u2.v [ 1 ]。 もし(D < 0 || u2.dist < D){ D = u2.dist。 q.push(U2)。 } } } ながら(D> = 0 ){ 場合(ANS [D]> = 0 ){ のprintf(" %D%D \ n "、ANS [D]、D)。 返します。 } D - 。 } } int型のmain(){ int型T、A、B、C、D。 scanf関数(" %のD "、&T)。 一方、(T-- ){ scanf関数(" %D%D%D%D "、&、&B、&C&D)。 (A、B、C、D)を解きます。 } 戻り 0 。 }