[ABC219H] Candles 题解
[ABC219H] Candles 题解
其实是挺有难度的一道题,是 这道题 的强化版。
显然人总是逐渐地远离原点。结合 \(n\le 300\) 的数据范围,考虑区间 dp。
显然的 dp 状态是设 \(dp_{i,j,t,0/1}\) 表示在区间 \([i,j]\) 中,时间为 \(t\),在左/右端点的最优答案。由于 \(t\) 的范围过大,这样做是不可行的。
对于弱化版,我们的解决方案是采用费用提前计算的思想。但是在本题中答案要对 \(0\) 取 \(\max\),因此同样不可行。
对于 \(O(n^3)\) 的数据范围我们可以再加一个维度。考虑如何将 \(t\) 代偿为一个 \(n\) 以内的值域。考虑费用提前计算不可行的原因是 部分蜡烛我们无法对它进行操作,因此我们加一维表示 还需要操作的蜡烛个数,即未处理且我们想要处理的蜡烛个数。
具体地,设 \(dp_{i,j,k,0/1}\) 表示在区间 \([i,j]\) 中,还有 \(k\) 个蜡烛需要操作,在左/右端点的最优答案。转移的式子便是容易的。
题目的关键是考虑代偿这个 \(t\),\(t\) 对题目的影响是判定一个蜡烛有没有效,我们转化其为直接选择每个蜡烛操作与否,会有许多不合法但不优的情况出现,但是我们总能枚举到最优的那个决策。
#include <bits/stdc++.h>
#define N 305
#define int long long
using namespace std;
int n;
struct Node {
int x, a;
bool operator < (const Node &p) const {
return x < p.x;
}
} e[N];
int dp[N][N][N][2];
// 定义 dp[i][j][k][0/1] 为在区间 [i, j],还有 k 个需要选择,在左右端点的最大答案
signed main() {
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%lld%lld", &e[i].x, &e[i].a);
e[++n] = {0, 0};
sort(e + 1, e + 1 + n);
int pos = 0;
for (int i = 1; i <= n; i++)
if (e[i].x == 0 && e[i].a == 0) {
pos = i;
break;
}
memset(dp, -0x3f, sizeof dp);
for (int k = 0; k <= n; k++)
dp[pos][pos][k][0] = dp[pos][pos][k][1] = 0;
for (int len = 1; len <= n; len++)
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
for (int k = 0; k <= n; k++) {
dp[i][j][k][0] = max(dp[i][j][k][0], dp[i + 1][j][k][0] - k * (e[i + 1].x - e[i].x));
dp[i][j][k][0] = max(dp[i][j][k][0], dp[i + 1][j][k + 1][0] - (k + 1) * (e[i + 1].x - e[i].x) + e[i].a);
dp[i][j][k][0] = max(dp[i][j][k][0], dp[i + 1][j][k][1] - k * (e[j].x - e[i].x));
dp[i][j][k][0] = max(dp[i][j][k][0], dp[i + 1][j][k + 1][1] - (k + 1) * (e[j].x - e[i].x) + e[i].a);
dp[i][j][k][1] = max(dp[i][j][k][1], dp[i][j - 1][k][1] - k * (e[j].x - e[j - 1].x));
dp[i][j][k][1] = max(dp[i][j][k][1], dp[i][j - 1][k + 1][1] - (k + 1) * (e[j].x - e[j - 1].x) + e[j].a);
dp[i][j][k][1] = max(dp[i][j][k][1], dp[i][j - 1][k][0] - k * (e[j].x - e[i].x));
dp[i][j][k][1] = max(dp[i][j][k][1], dp[i][j - 1][k + 1][0] - (k + 1) * (e[j].x - e[i].x) + e[j].a);
}
}
cout << max(dp[1][n][0][0], dp[1][n][0][1]) << "\n";
return 0;
}

浙公网安备 33010602011771号