質問の意味:nはあなたの現在の重量を与えるが、あなたは体重Mの贈り物を動かす一回よりも多くを見ていない、あなたはMパワーを与えます。
アイデア:バックパックには思えるが、Mあまりにも。したがって、DFSを使用して、Nも45、最初の検索DFSは、ケースの最初の半分の重量の全てが満たさ検討し、次に重量双方向ように、次いでさらに後半、半回答を検索します。
書式#include <cstdioを> する#include <CStringの> の#include <アルゴリズム> 書式#include <ベクトル> の#include <マップ> 書式#include <キュー> の#defineは長い長いでしょ 使用して 名前空間はstdを、 CONSTの INT MAXN =(1 << 24)+ 10 。 LL N、M。 LL [MAXN]、B [MAXN]。 LL K; ANS LL; ブールCMP(LLのB、LL) { 戻り > Bと、 } (LL和)を見つけるllの { // のprintf( "M-合計:%LLDする\ n"、M-合計)。 int型のy =K; もし(B [Y]> M- 和) Y = UPPER_BOUND(B + 1、B + 1 + K、M-和)-B- 1 。 // のprintf( "Y:%Dを\ n"、Y); ANS = MAX(ANS、B [Y] + 和)。 } INT DFS(INT X、LLの合計) { 場合(X ==(N / 2 + 2)+ 1 ) { B [ ++ K] = 和。 リターン 1 ; } DFS(X + 1 、合計)。 もし(和+ [X] <= M) DFS(X+ 1、和+ [X])。 } INT DFS2(INT X、LLの合計) { 場合(X == N + 1 ) { (和)を見つけます。 リターン 1 ; } DFS2(X + 1 、合計)。 もし(和+ [X] <= M) DFS2(X + 1、和+ [X])。 } int型のmain() { scanf関数(" %のLLDの%のLLD "、&M、&N) 用(int型 iは= 1、I ++; iが<= N。) { scanf関数(" %のLLD "、および[I])。 } ソート(A + 1、A + N + 1 、CMP)。 DFS(1、0 ); ソート(B + 1、B + K + 1 )。 K =一意(B + 1、B + K + 1) - (B + 1 )。 DFS2(N / 2 + 3、0 ); printf(" %LLDする\ n " 、ANS)。 }