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 ; } } }