複数のバックパック+バイナリ分割POJ1014

問題の意味:いくつかのブロックと1,2,3,4,5,6大理石、それぞれの正しい値は、2部は等しい重みにそれらを置くことができます。大理石の総数は20,000を超えてはなりません。(複数のバックパック)

分析:裁判官のDP [V / 2] == V / 2をすることができますが、プロセスは、01バックパックなど、複数のバックパックは、非効率的に通常の慣行場合バイナリー分割の最適化を使用するには、この時間をタイムアウトします、変更の複雑さあります image.png

バイナリ分割原理:image.png

image.png

ここで、任意の数であれば、私たちはそれぞれに番号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 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/-Zzz-/p/11415834.html