質問が意図される:放送ユニット(バックパック)に、そしてあなたが期間n個(容量)を再生し、各テープに対応するmは、各テープを再生することができ、自身の時間(容量)、最大シーク時間を持っており、選択したテープ(バックパックの最大容量を詰めと項目選択することができる)、各テープは一度だけ再生出力します。
思考:これは0/1ナップザック問題である(アイテムは一度だけ使用することができる)、選択した項目への出力のコントラストつつ。私たちは、記録するために、二次元DPを使用します(一次元が最後にどの項目の最終的な選択を記録することはできません)
もしDP [I] [J] == DP [I- 1] [JV [I]] + V [i]は、これはまさに最後の転送を超えるパスに沿ったものであることを意味し、それはあるので、あなたが(前回の記事を取り戻すことができます彼らは出力が逆になりますので)、逆の順序で項目を取得
完全なコード:
#include <iostreamの> する#include <cstdioを> する#include <CStringの> のconst int型 MAXN = 1E5。 INT DP [ 30 ] [MAXN]。 int型のV [MAXN]。 int型ANS [MAXN]。 使用して 名前空間はstdを、 INT のmain(){ int型N、M。 一方、(〜のscanf(" %D%dの"、&N、&M)){ memsetの(DP、0、はsizeof (DP))。 以下のために(int型私= 1 ; I <= M; iが++ ){ scanf関数(" %のD "、&V [I])。 } のための(int型 I = 1 ; I <= M; iが++ ){ ため(int型 K = N; K> 0 ; k-- ){ DP [I] [K] + = MAX(DP [I- 1 ] [ KV [I] + V [i]は、DP [I- 1 ] [k]を)。 もし(K <V [i])とDP [I] [k]はDPを= [I- 1 ] [K]; } } int型の CNT = 0 。 用(int型 I = M、J = N; I> 0 ; I - ){ // 下标与背包容量 もし(JV [i]が> = 0 && DP [I] [J] == DP [I- 1 ] [JV [I] + V [I]){ ANS [CNT ++] = V [i]は、// 从V [i]は处推导来 J - = V [i]は、 } } のために(int型 I = CNT- 1 ; I> = 0 ; i-- ){ COUT << ANS [I] << " " 。 } COUT << " 合計:" << DP [M] [N] << ENDL。 } }