0w1

HE Zulu visits Wonderland ( DP )

https://www.hackerearth.com/challenge/competitive/may-circuits-17/algorithm/zulu-visits-wonderla-1/

題意:
N 層的地下迷宮,M 種物品。
在時間 x,你能拿第 i 個物品若且唯若所有 Level 比 Level[ i ] 小的物品的過期時間不早於 x,並且 x + Time[ i ] 不晚於 E[ i ]。
問最大總價值。

制約:
1≤N,M≤2000
1≤Value≤1e9
1≤Time,E[i]≤2000
1 ≤ Level[ i ] ≤ N

解法:
優先考慮早過期的物品,倒著時間進行動態規劃。

複雜度:
O( M * MAXT )

#include <bits/stdc++.h>
using namespace std;
 
template< class T1, class T2 >
int upmax( T1 &x, T2 v ) {
  if( x >= v ) return 0;
  x = v;
  return 1;
}
 
const int MAXN = 2000;
const int MAXM = 2000;
const int MAXV = int( 1e9 );
const int MAXT = 2000;
 
int N, M;
int E[ MAXN ];
int pme[ MAXN + 1 ];
int V[ MAXM ], T[ MAXM ], L[ MAXM ];
int ord[ MAXM ];
 
long long dp[ MAXT + 1 ];
 
signed main() {
  ios::sync_with_stdio( 0 );
  cin >> N >> M;
  pme[ 0 ] = 0x3f3f3f3f;
  for( int i = 0; i < N; ++i ) {
    cin >> E[ i ];
    pme[ i + 1 ] = min( pme[ i ], E[ i ] );
  }
  for( int i = 0; i < M; ++i ) {
    cin >> V[ i ] >> T[ i ] >> L[ i ];
    --L[ i ]; // 0 idx
    ord[ i ] = i;
  }
  auto st = [ & ]( int x ) { return min( E[ L[ x ] ], pme[ L[ x ] ] ); };
  sort( ord, ord + M, [ & ]( int i, int j ) { return st( i ) > st( j ); } );
  for( int i = 0; i < M; ++i ) {
    long long maxt = 0;
    for( int j = MAXT; j >= st( ord[ i ] ); --j ) {
      upmax( maxt, dp[ j ] );
    }
    for( int j = st( ord[ i ] ); j >= T[ ord[ i ] ]; upmax( maxt, dp[ --j ] ) ) {
      upmax( dp[ j - T[ ord[ i ] ] ], maxt + V[ ord[ i ] ] );
    }
  }
  cout << *max_element( dp, dp + MAXT + 1 ) << endl;
  return 0;
}