和のための学校オフ第フィールドタイトルDバイナリ列挙(大リュック)の合成和以上2019頭の牛

https://ac.nowcoder.com/login?callBack=%2Facm%2Fcontest%2F889%2FD%3F%26headNav%3Dacm

問題の意味:指定された長さnの配列{I}との和の和。

サブセット和、01の合計は、シーケンスプログラムの出力を選択するように、サブセットの{I}を見つけてください。

分析:普通のバックパック、n個の、時間の複雑さ* [i]の(max)が行う、と[i]は、あまりにも、明らかにタイムアウト、または暴力的な列挙行い、その後、2 ^ n個になるように、大きなバックパックとして見ることができますまた、残業が、唯一の36 N、インデックスバイナリバイナリ列挙を使用し、それはかなりの時間の複雑さを低減することができます。

数が設定、および検索(のセット)を使用するには大きすぎるので、見つけるための第2の列挙中!= Set.end()が達成されるかどうかを調べる、及び01選択されたプログラムの出力シーケンスにおいて、出力は最初の列挙方式を持っていたように、第1の時間計数のための状態との和を保存するためにマップを使用します。

 

#include <cstdioを> 
する#include <CStringの> 
する#include <iostreamの> 
する#include <アルゴリズム> 
の#include < 設定 > 
の#include <地図>
 使用して 名前空間STD。

typedefの長い 長いLL。
INTのN、Q、P。
LLの合計。
LL [ 39 ]。
セット <LL> SE。
マップ <LL、int型 > ミリアンペア。

INT メイン(){ 
    scanf関数(" %d個の%のLLD "、&​​N、&合計)。
    P = N >>1 );
    以下のためにint型私= 1 ; iが<= N; iが++ ){ 
        scanf関数(" %のLLD "、A + I)。
    } 
    ためにint型 i = 1 ; iが(< 1 << P)を、iが++ ){ 
        LL RES = 0 int型 J = 0 ; J <P; J ++ ){
             場合(I&(1 << J))
                RES + = [J + 1 ]。
        }  
        se.insert(RES)。
        MA [RES] =私; 
    } 
    のためのint型 i = 1 ; iが(< 1 << q)を、iが++ ){ 
        LL RES = 0 int型 J = 0 ; J <Q; J ++ ){
             場合(I&(1 << J))
                RES + = [P + J + 1 ]。
        } 
        であれば(se.find(SUM-RES)=!se.end()){
             int型状態MA = [sum- RES]。
            int型のk = 0 ; K <Pあり、k ++ ){
                もし(状態&(1 << K))のputchar(' 1 ' )。
                のputchar(' 0 ' ); 
            } 
            のためのint型のk = 0 ; K <Q; ++ k個){
                 場合(I&(1 << K))のputchar(' 1 ' )。
                のputchar(' 0 ' ); 
            } 
            プット("" )。
            リターン 0  ;
        } 
    } 
}

 

おすすめ

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