[ABC219H] Candles 题解

[ABC219H] Candles 题解

其实是挺有难度的一道题,是 这道题 的强化版。

显然人总是逐渐地远离原点。结合 n300 的数据范围,考虑区间 dp。

显然的 dp 状态是设 dpi,j,t,0/1 表示在区间 [i,j] 中,时间为 t,在左/右端点的最优答案。由于 t 的范围过大,这样做是不可行的。

对于弱化版,我们的解决方案是采用费用提前计算的思想。但是在本题中答案要对 0max,因此同样不可行。

对于 O(n3) 的数据范围我们可以再加一个维度。考虑如何将 t 代偿为一个 n 以内的值域。考虑费用提前计算不可行的原因是 部分蜡烛我们无法对它进行操作,因此我们加一维表示 还需要操作的蜡烛个数,即未处理且我们想要处理的蜡烛个数。

具体地,设 dpi,j,k,0/1 表示在区间 [i,j] 中,还有 k 个蜡烛需要操作,在左/右端点的最优答案。转移的式子便是容易的。

题目的关键是考虑代偿这个 tt 对题目的影响是判定一个蜡烛有没有效,我们转化其为直接选择每个蜡烛操作与否,会有许多不合法但不优的情况出现,但是我们总能枚举到最优的那个决策。

#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;
}
posted @   长安19路  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示