C - ピザを注文
C - ピザを注文
これは貪欲、非常に古典的な、最も困難ですが、私は、どのように貪欲知って早けれ研修の最後として、問題の解決策を読んでいないだろう。
これは、2つのプライオリティキュー内に置かれた誰もが、BAの並べ替えを最初に答えを見つけることです、彼のお気に入りを食べ、その後、従うことができると仮定することで、
Bの場合>第2のブロック、最初のブロックを食べたり上昇リーチにソートするプライオリティキューに、得られたNUMを食べます。
NUM1食べるレコード数、食べるための第2のブロックのレコードのNUM2番号。
NUM1%= S、NUM2%= sの数がより大きいまたは等しいNUM1 + NUM2はSを満たすように記述されている場合。
彼らだけ食べるようにいずれかを選択することができていることを示す、秒未満の場合、この時間は貪欲後に答えを見つけるために、貪欲は、最小限の努力がものを食べることになり取ります。
両サイド貪欲プライオリティキューを使用しました。
良い話題。
書式#include <cstdioを> する#include <CStringの> の#include <cstdlib> 書式#include <アルゴリズム> 書式#include <キュー> の#include <ベクトル> の#include <iostreamの> の#include < 文字列 > に#define INF 0x3f3f3f3f の#define inf64 0x3f3f3f3f3f3f3f3f 使用して 名前空間STD; const int型 MAXN = 1E5 + 10 。 typedefの長い 長いLL。 構造体ノード{ int型NUM、幸せ。 ノード(INT NUM = 0、int型幸せ= 0 NUM(NUM)、幸せ(幸せ){}) ブール 演算子 <(constのノード&A)のconst { 戻り a.happy < 幸せ。 } }。 PRIORITY_QUEUE <ノード> V1、V2。 int型[MAXN] B、[MAXN]。 INT )(主 { LL N、S。 scanf関数(" %のLLDの%のLLD "、&N、&S)。 LL NUM1 = 0、NUM2 = 0、ANS = 0 。 以下のための(int型私は=1 ; iが<= N; iが++ ) { int型NUM。 scanf関数(" %D%D%D "、およびNUM、&[i]は、&B [I])。 もし([I]> [I] B)NUM1 + = NUM、v1.push(ノード(NUM、[I] - B [I]))。 他 NUM2 + = NUM、v2.push(ノード(NUM、B [1] - [I]))。 ANS + = NUM *の1LLの*の最大値([I]、B [I])。 } NUM1%= S、NUM2%= Sであり; もし(NUM1 + NUM2> S)のprintf(" %LLDする\ n " 、ANS)。 他 { // のprintf( "NUM1 =%LLD NUM2 =%LLD ANS =%LLD \ n"は、NUM1、NUM2、ANS)。 LL RES1 = 0、cost1 = 0、RES2 = 0、cost2 = 0 。 一方、(!v1.empty()) { ノードU = v1.top()。v1.pop(); int型 NUM = u.num。 もし(RES1 + NUM> = NUM1) { cost1 + =(NUM1 - RES1)* u.happy。 破ります; } RES1 + = NUM。 cost1 + = NUM * u.happy。 } しばらく(!v2.empty()) { ノードU = v2.top()。v2.pop(); int型 NUM = u.num。 もし(RES2 + NUM> = NUM2) { cost2 + =(NUM2 - RES2)* u.happy。 破ります; } RES2 + = NUM。 cost2 + = NUM * u.happy。 // のprintf( "cost2 =") } // のprintf( "cost2 =%LLD \ n"、cost2)。 ANS = MAX(ANS - cost1、ANS - cost2)。 printf(" %LLDする\ n " 、ANS)。 } 戻り 0 。 }