E - サラ・ネバーランド
私はそれは難しい問題の解決策を確認するために見つけるトピックを長時間見ています。
まず大まかなアイデアがグループ化されているのと同じ番号がグループBに分けられて、それぞれの番号が* 2 ^ Bに分けることができます取得します。
各グループ内で行わ01バックパックは、この操作は比較的簡単です。
より多くの困難は、グループ間で転送されます。
定義されたDP [i] [j]はJ * 2 ^ Iのi層の容量の最大値を表します。
だから、どのように私からの転送私は何層に1層?
+ J前の総容量は* 2 ^ iはW +((1 << I)-1)となるようDP [i]はi層の容量[j]は、i番目の層自体の容量であるため
唯一のi番目の層(JK)* 2 ^ Iあまり容量は、第(I-1)マルチレイヤもKであってもよい* 2 ^ Iそれほど容量を仮定する。
これはどのようにそれが好き転送こと?
DP [I-1]から想定[X]のI-1 X * 2 ^(I-1)容量層から転送されています
最後にi層jの合計ため* 2 ^ iが+ W・((1 << I)-1)i番目の層(JK)の容量* 2 ^ I容量
(JK)* 2 ^ I - X * 2 ^ 2 ^ iはW&+ *(I-1)= J((1 << I)-1)を所以
解出X = 2 * K +(W >>(I-1)&1)
したがって、転写式DP [I] [J] = MAX(DP [I]、[J]、DP [I-1] [2 * K +(W >>(I-1)&1)])
同じグループに配置され、これらn個の石、及び* 2 ^ bは10の最大のものである場合にのみ、n個の宝石の合計は、この第二の寸法は、10×n個であるため
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
書式#include <cstdioを> する#include <CStringの> の#include <cstdlib> 書式#include <キュー> の#include <アルゴリズム> 書式#include <iostreamの> に#define 0x3f3f3f3f INF 使用して 名前空間はstdを、 const int型 MAXN = 1000年 + 10 。 typedefの長い 長いLL。 INT DP [ 35 ] [ 1010 ]。 INT のmain(){ int型N、M。 一方、(scanf関数(" %d個の%のD "! - 、&N、&M)&& N =1 && M =! - 1 ){ memsetの(DP、0、はsizeof (DP))。 以下のために(int型 iは= 1 ; iがn = <; iは++ ){ int型のVal、W = 0 ; scanf関数(" %dの%のD "、白黒、およびヴァル)。 一方、(重量%2 == 0)/ W = 2、++ 。 用(INT J = 1000年 ; J> = W; j--)DP [A] [J] = MAX(DP [A]、[J]、DP [A] [J - W] + val)で、 } INT W = M、最大= 0 。 以下のために(int型私は、W =; I; Iは>> = 1)アップ++。up-- ; 以下のために(int型私= 1 ; iが<=最大; iが++ ){ ため(INT J = 1000 ; J> = 0 ; j-- ){ ため(int型 = K 0 ; <= J kは、kは++ ){ DP [I ] [J] = MAX(DP [I]、[J]、DP [I] [J - K] + DP [I - 1 ] [分(1000年、2 * K +((W >>(I - 1))&1 ))])。 } } } のprintf(" %d個の\ n "、DP [最大] [ 1 ])。 } 戻り 0 。 }