質問の意味:
n日前、投資プログラムのM種類、および[X] K F以下の補助金残高があります。
あなたが投資プログラムの数は無制限に投資することを選択することができます毎日(ただし、そのバランスが0以上であることを確認するため)、投資収益は、n日間返品の終了後になります。
投資の最大のリターンを求めていることはどのくらいです。
アイデア:
この投資のお金が、その後、最後の収穫は、完全なナップザック問題に変換することができます。多様な毎日のバランスの状態はとても毎日が始まるので、ステートに移行しなければなりません。
i日のために提供DP [I] [J]、バランスJ。次に、状態遷移は毎日開始:DP = MAX(DP [I] [J + F [J]、DP [I-1]〜[J])[I] [J] F jは+]; // F [ j]は、補助金の関数であり、
その後、同じ日に完全にバックパックに転送
コード:(他のコードのコメントを参照してください)
#include <iostreamの> する#include <cstdioを> する#include <CStringの> 使用して 名前空間STD; CONST INT INF = 0x3f3f3f3f ; INT F [ 2050 ]; // (0 <= K <= 1000)、(K + F [K] <= 2000) のint V [ 110 ]、W [ 110 ]; // 。(1 <= M <= 100) INT DP [ 105 ] [ 3005 ]; // MAX(Iは+ F [I]) INT メイン() { int型N-、M、K; CIN >> M >> N- K; // 曜針残金最大に INTMmaxの= 0 ; 以下のために(int型 i = 0 ; iは= Kを<I ++は{) のscanf(" %dの"、&F [i])とします。 Mmaxを = MAX(Mmaxを、F [i]が+ I)。 } のために(int型 I = 1 ; I <= M; iは++ ){ scanf関数(" %d個の%のD "、&V [i]は、&W [I])。 } のmemset(DP、 -INF、はsizeof (DP))。 DP [ 1 ] [ 0 ] = 0 。 以下のための(int型L = 2、L <= N; L ++ ){ ための(int型 J = 0 ; J <= kであり、j ++ ) DP [L] [J + F [J] = MAX(DP [L] [J + F [ J]、DP [1- 1 ] [J])。 以下のために(int型 I = 1 ; I <= M; iは++ ){ ため(INT J = Mmaxを-V族[i]は、J> = 0 ; j-- ){ DP [L] [J] = MAX(DP [L ] [J]、DP [L] [J + V [i]は] + [I])W。 } } } // 最后一天状态更新 INT ANS = 0 。 以下のための(int型 i = 0 ; iは= Mmaxをを<; iは++ ){ ANS = MAX(ANS、DP [n]は[I] + iは+ Fを[I])。 } COUT << ANS << ENDL。 }