题解 P1651 塔 (非常好的DP题!!!)

AC通道

非常好的 $ dp$ 题, 在复健运动中居然没想出来这么 \(dp\)。值得记录。详情看代码

#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
	T x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
	a = x * s;
	return ;
}

int dp[3][500001];       // 前 i 个木块,差为 j, 高的那个塔的最大高度
int n;
int a[51]; 
int H; 

int main(){
  // freopen("hh.txt", "r", stdin); 
  // freopen("out.txt", "w", stdout); 
  read(n);
  for(int i = 1; i <= n; i++) read(a[i]), H += a[i];

  memset(dp, -0x3f, sizeof(dp)); 
  dp[0][0] = 0; 
  for(int i = 1; i <= n; i++){
    for(int j = 0; j <= H; j++){
      dp[i&1][j] = max(dp[(i&1)^1][j+a[i]], dp[(i&1)^1][j]); 
      if(j - a[i] >= 0) dp[i&1][j] = max(dp[i&1][j], dp[(i&1)^1][j-a[i]] + a[i]);
      else dp[i&1][j] = max(dp[i&1][j], dp[(i&1)^1][abs(j-a[i])] + j);    // 差值比 a[i] 小才能矮变高
    }
  }


  // 如果放在高的那个 dp[i][j] = dp[i-1][j-a[i]] + a[i]
  // 如果不放   dp[i][j] = dp[i-1][j]
  // 放矮的那个,仍然矮: dp[i][j] = dp[i-1][j+a[i]] 
  // 矮变高:   dp[i][j] = dp[i-1][abs(j-a[i])] + j 
  if(dp[n&1][0] > 0)
    cout << dp[n&1][0] << endl; 
  else cout << -1 << endl; 
  return 0;
}




posted @ 2022-09-20 23:55  雪之下,树之旁  阅读(14)  评论(0编辑  收藏  举报