質問の意味:あなたはお金の最大量は、以下のモデルを得ることができます計算しますか:
あり 、あなたのお金がある最初の数n日 0は、そこにされている 最初の、可能な操作をmは 、私は 一種のあなたが現在失わせる 私の お金の量をし、中 一日n個の終了後に復帰 B 私は お金を数えるが。毎日は、(各操作の後に、しかし、あなたが否定することはできませんお金の量)任意の回数のそれぞれの操作の任意の数を実行することができます。毎日の終わりには、現在とお金のホールドを取得 X関連の所得F (xと)、および fは(X )は単調増加しません。
分析:まず、明らかに動的プログラミング、および状態が日前、私に分解することができ、現在開催された金額は、投資に関する最終リターンを得ることができます。最大値として、2つの配列のインデックスの小さい方を選択します。
次に、状態遷移方程式:プロセス日I許容節転移が得られました
DP [i]は[W jは+ = MAX(DP [I] [J + W [J]、DP [I-1]〜[J])[J] 前者によるそのような状態の二日目に状態への日帰り転送。
ストレージノードのプロセスについては、それぞれあなたが完全なバックパックを行うことができる唯一の方法を保存します。
注:この状態は完全にバックパックが新しいフォームである私たちは皆知っている、ベースの状態jのナップザック問題は、総容量を指している、とjの状態は、この質問は、手持ちのお金を意味し、それは、残りの容量です。我々は、状態遷移方程式を書く方法を知っている現実的な理解をシミュレートします。列挙方向に注意してください。
注意:まだ非アクティブ状態に転送されていない、それは非常に小さい負の数に設定する必要があります。
#include <ビット/ STDC ++ H.> 使用して 名前空間STD; CONST INT INF = 0x3f3f3f3f ; INT A [ 105 ]、B [ 105 ]; INT W [ 1005 ]; int型 DP [ 105 ] [ 1005 + 1005 ]; //を表し状態は、最初の日の私の手元にあります!残り!お金(値)投資が最もどのくらいであってもよい INT )(主{ int型N-、M、K; scanfの(" %D%D%D "、およびN-、&M&K) のための(int型私は= 0 ; Iは<= K; I ++ ){ scanf関数(" %dの"、W + I)。 } のための(int型 I = 1 ; I <= M; iが++ ){ scanf関数(" %d個の%のD "、A + I B + I)。 } のために(int型 i = 1 ; iが<= N; iが++ ){ ため(INT J = 0 ; J <= 2005 ; J ++ ){ DP [I] [J] = - INF。 } } DP [ 1 ] [ 0 ] = 0 。 以下のために(int型 I = 2 ; I <= N; I ++は){ ため(INT J = 0 ; J <= 1000年 ; J ++ ){ DP [I]、[J + W [J] = MAX(DP [I] [ W + J [J]、DP [I- 1 ] [J]); } のための(int型 K = 1。 <; K ++ = M、K ){ ため(INT J = 1000年 ; J> = 0 ; J、){ DP [I] [J] = MAX(DP [I]、[J]、DP [I] [J + [K] + B [K]); // J通常、本明細書には、バックパックの総容量を指し、つまり、手持ちのお金の残り容量があることを意味し、その状態遷移方程式を書く方法を知っているかのシミュレーションを現実的に理解しています } } } int型 ANS = - 1 。 以下のために(int型 i = 0 ; iが= < 1000 ; iが++ ){ ANS = MAX(ANS、DP [n]はiは+ [I] + [I] W) } のprintf(" %d個の\ n " 、ANS)。 }