問題の意味:いくつかのブロックと1,2,3,4,5,6大理石、それぞれの正しい値は、2部は等しい重みにそれらを置くことができます。大理石の総数は20,000を超えてはなりません。(複数のバックパック)
分析:裁判官のDP [V / 2] == V / 2をすることができますが、プロセスは、01バックパックなど、複数のバックパックは、非効率的に通常の慣行場合バイナリー分割の最適化を使用するには、この時間をタイムアウトします、変更の複雑さあります
バイナリ分割原理:
ここで、任意の数であれば、私たちはそれぞれに番号1を有するので、大きな数で表すことができる多数11101111は、1248であることを意味する(1101001000 ..)発現させることができます、その後、任意の数は、それぞれ二進数の便宜のために、プロセスにバイナリ数を経ることができる唯一のものである13 1,2,4,6に分割されるように、この方法は、取り扱いが最後の6やすい(見ることができます)重複を避けます。
バイナリ分割:
用(INT I = 1 ; I <= N; I ++は) { ため(INT J = 1。 ; J <[I] NUMが=、J = << 1 ) // 。バイナリ各列挙 // NOTE若い年齢大分割する { NUM [I] - = J; // 分社減算 new_cを【TOTが++] = J * C [I]; // 物品の大量の合成 [TOT = J new_w W [I] *; // 物の大きな値の合成 } のiF(NUM [I])// 存在するかどうかを決定するの残りの部分。 // 我々が特定のアイテム13を有する場合、明らかなようにバイナリに分割1,2,4。 // 私たちはの一部のうち、6人以上を持っているので、彼らは別のサービス提供を必要としています。 { new_cを[TOT ++] = NUM [I] * C [i]は、 new_w [TOT] = NUM [I] * X [i]は、 NUM [I] = 0 ; } }
コード:
#include <cstdioを> する#include <CStringの> する#include <iostreamの> する#include <アルゴリズム> の#define 0x3f3f3f3f INF 使用して 名前空間STDを、 const int型 MAXN = 120012 ; int型nは、V。 int型DP [MAXN]。 int型 [ 7 ]。 int型V [MAXN]、[MAXN] W。 INT のmain(){ int型カセ= 1 。 一方、(scanf関数(" %D%D%D%D%D%D "、&[ 1 ]、及び[ 2 ]、および[ 3]、および[ 4 ]、および[ 5 ]、および[ 6 ])!= EOF){ 場合([ 1 ] == 0 && [ 2 ] == 0 && [ 3 ] == 0 && [ 4 ] = = 0 && [ 5 ] == 0 && [ 6 ] == 0)破ります。 memsetの(DP、0、はsizeof (DP))。 printf(" コレクション#%dを:\ N "、加瀬++ ); V = N = 0; 以下のために(int型 i = 1 ; iが<= 6 ; I ++ ){ V + = [I] * I。 } もし(V&1 ){ のprintf(" 分割できない\ n \ n。" ); 続け; } 他{ INT TOT = 0 。 以下のために(int型 i = 1 ; iが<= 6 ; I ++ ){ ため(INT J = 1; J <= [i]は、J << = 1 ){ [I] - = J。 // のprintf( "[I] =%DJ =%D \ n"は、[I]、j)は、 W [TOT = jは* I。 V [TOT ++] = J * I。 } 場合([I] =!0 ){ V [TOT]が [I] * = iは、 W [TOT ++] = [I] * I。 } } // のprintf( "TOT =%d個の\ n"、TOT)。 以下のために(int型 i = 0 ; iはTOT <; iは++ ){ 用(INT J = V / 2 ; J> = W [I]; j-- ){ DP [J] = MAX(DP [J]、DP [JW [I] + V [I])。 } } // ため(INT I = 6; I> = 1; I - ){ // ため(INT K = V / 2; K> = I; K - ){ // ため(INT J = 1 ; J <= A [i]は、J ++){ // (KI * J場合> = 0) // DP [k]が最大値(DP [k]は、DPの[用のKi * jを] = + iがjは*)。 // /// /のprintf( "DP [K] =%Dを\ n"、DP [K])。 // } // } // } もし(DP [V / 2 ] == V / 2 ) のprintf(" 分割することができる\ n \ n。" ); 他の printf関数(" 分割することはできません\ N \ N。" ); } } 戻り 0 。 }