質問の意味:Nのタスクがありますが、あなたの最初の評価は、2つの指標を持っているM、Nの作業です:このタスクの完了後、このタスクに必要な最低の評価([i])との完了と同様に、格付けの変更( (B [I]))が負であってもよいです。評価は負にすることはできません。F1:注文を完了するためにタスクがある場合、それはすべてのタスクが完了することができて前に、お願いします。F2:あなたは、完了するために、タスクの任意の数を選択するまでに完了することができますどのように多くのタスクを依頼することができます。
アイデア:
F1:定格の立ち上がりと立ち下がりの評価:最初のタスクは、2つの部分に分かれています。[i]は小から大まで注文することができに従い、直接評価アップタスクについて。なぜ?評価は、あなたがすべてを完了することができた場合、タスクは確かに、他のタスクの完了後に完了することができます完了することができ、以前は、完了後に元の定格よりも小さくなることはありませんので、評価区間を下げることを検討し始めました。私たちは、降順で、我々は、各タスクの実行後の評価は、下限を検討評価セクションの減少、およびプレス円を考慮し、それは、好みに大きなタスク、背中の下限の高い小さなインパクトの下限です。
コード:
#include <ビット/ STDC ++ H> の#define INF 0x3f3f3f3f 名前空間stdを使用。 CONST INT MAXN = 110。 構造体ノード{ int型X、Y。 }。 ベクター<ノード>、B。 BOOL CMP1(ノードT1、ノードT2){ t1.x <t2.x返します。 } ブールCMP2(ノードT1、ノードT2){ リターン(MAX(t1.x、-t1.y)+ t1.y)>(MAX(t2.x、-t2.y)+ t2.y)。 } int型のmain(){ int型N、M、CNT1 = 0、CNT2 = 0。 scanf関数( "%d個の%のD"、&N、&M)。 int型の合計= 0; ノードTMP; (I 1 = int型、iが<= N; iが++){ため のscanf( "%D%D"、&tmp.x、&tmp.y)。 IF(tmp.y> = 0)a.push_back(TMP)。 他b.push_back(TMP); } ソート(a.begin()、。 ソート(b.begin()、b.end()、CMP2)。 int型ANS = 0; 以下のために(INT i = 0; i)は(a.sizeを<; iは++){ IF(M <[I] .X)ANS = -1。 M + = A [i]の.Y。 } ための式(I = 0 int型、iがb.sizeを()<; I ++)は{ (M <B [i]は.X)ANS = -1の場合、 M + = B [i]は.Y。 } IF(ANS == -1)のprintf( "NOの\ n"); 他のprintf( "YES \ nを"); }
F2:これは明らかに直接バックパックDP、DPであるが、選択は残りのタスクに影響を与えるので、各タスクのO(N×n個×m個)です。DPこのタイムアウト。F1の我々は単に選択するか、我々は一種の下限に合わせてドロップの評価の一部を置けばラインで選択し、優先度の高いタスクの上限を選択するために、現在のタスクを列挙結論ので、我々DP転送することで、そのような決定がされているので、最適なので、DPプロセスの複雑さはO(n×m個)を完成させることができるように、前のタスクが完了したの影響を考慮する必要がありません。
コード:
#include <ビット/ STDC ++ H> に#define PII対<整数、整数> 名前空間stdを使用。 const int型MAXN = 600010; INTのDP [110] [MAXN]。 ブールCMP(PIIさt1、t2のPII){ リターン(t1.first + t1.second)>(t2.first + t2.second)。 } ベクトル<PII> A、B。 INTのmain(){ int型N、M。 scanf関数( "%d個の%のD"、&N、&M)。 PII TMP; 以下のために(INT i = 1; iが<= N; iは++){ scanf関数( "%d個の%のD"、&tmp.first、&tmp.second)。 IF(tmp.second> = 0)a.push_back(TMP)。 他b.push_back(TMP); } ソート(a.begin()、a.end())。 ソート(b.begin()、b.end()、CMP); INT MX = M、TOT = 0。 以下のために(INT i = 0; i)は(a.sizeを<; iは++します){ [i]が1次回(IF < TOT ++。 } } int型ANS = 0。 DP [0] [MX] = TOT。 以下のために(INT i = 0; i)は(b.sizeを<; iは++){ ための(int型J = 0であり、j <= MX; J ++){ IF(J> = B [i]は1次回&& J + B [I ] .second> = 0){ DP [I + 1] [j + B [i]は.second] = MAX(DP [I + 1] [j + B [i]は.second]、DP [I] [J ] + 1)。 } DP [I + 1]〜[J] = MAX(DP [I + 1] [j]は、DP [I] [J])。 } } のために(INT i = 0; I <= MX; iは++){ ANS = MAX(ANS、DP [b.size()] [I])。 } のprintf( "%d個の\ n"、ANS)。 }