ABC219H Candles

[ABC219H] Candles

很像 关路灯 这玩意儿啊,容易想到区间 DP

仿照那道题,可以考虑设出状态,即 当前已经熄掉的区间 [L,R],与 当前所在端点 0/1

我们有如下转移

fl,r,0=max(fl+1,r,0(Nr+l)Dis(l,l+1),fl+1,r,1(Nr+l)Dis(l,r))fl,r,1=max(fl,r1,0(Nr+l)Dis(l,r),fl,r1,1(Nr+l)Dis(r1,r))

但是这题的区别就在于 蜡烛是会熄灭的

也就是如果按 上式转移当发生蜡烛已经熄灭时人才到位的情况时,贡献会错

于是我们可以考虑 多设一种状态,用 k 表示 之后还有多少蜡烛要被熄灭

每次的转移我们考虑 这个蜡烛是否已经熄灭,换言之就是 是否要被熄灭

  1. 如果其已经熄灭,即 它不用被熄灭(之后还需熄灭的蜡烛不变,故从 k 转移过来)

    fl,r,k,0 将从 fl+1,r,k,0,fl+1,r,k,1转移,且 不会加上这个蜡烛的贡献 Al

    fl,r,k,1 将从 fl,r1,k,0,fl,r1,k,1转移,且 不会加上这个蜡烛的贡献 Ar

  2. 如果其还没熄灭,即 现在把它熄灭(之后还需熄灭的蜡烛 1,故从 k+1 转移过来)

    fl,r,k,0 将从 fl+1,r,k+1,0,fl+1,r,k+1,1转移,且 应当加上这个蜡烛的贡献 Al

    fl,r,k,1 将从 fl,r1,k+1,0,fl,r1,k+1,1转移,且 应当加上这个蜡烛的贡献 Ar

而由于我们当前有 k 个蜡烛 还需熄灭,也就是 只考虑这 k 个蜡烛 还在燃烧

故我们的 花费Dis)应当乘上 k 这个系数,而非之前的 Nr+l所有没到达的

于是最终转移式如下

fl,r,k,0=max(fl+1,r,k,0kDis(l,l+1),fl+1,r,k,1kDis(l,r),fl+1,r,k+1,0(k+1)Dis(l,l+1)+Al,fl+1,r,k+1,1(k+1)Dis(l,r)+Al)fl,r,k,1=max(fl,r1,k,0kDis(l,r),fl,r1,k,1kDis(r1,r),fl,r1,k+1,0(k+1)Dis(l,r)+Ar,fl,r1,k+1,1(k+1)Dis(r1,r)+Ar)

然后我们可以写出这样的代码

注意到 剩余需要熄灭的蜡烛 不可能比 剩余蜡烛 多,所以枚举 k 的时候可以 适当剪枝,见下

#include <bits/stdc++.h>

const int MAXN = 305;

using namespace std;

long long F[MAXN][MAXN][MAXN][2];

struct Candle {
	int x, l;
	inline bool operator < (const Candle &a) const {
		return x < a.x;
	}
} C[MAXN];

inline long long Dis (const int L, const int R) {
	return 0ll + C[R].x - C[L].x;
}

int N, T, r;

signed main () {
	
	cin >> N;
	
	for (int i = 1; i <= N; ++ i) cin >> C[i].x >> C[i].l;
	
	C[++ N] = {0, 0};
	
	sort (C + 1, C + N + 1);
	
	for (int i = 1; i <= N; ++ i) if (!C[i].l) {T = i; break ;}
	
	memset (F, -127, sizeof F);
	
	for (int i = 0; i <= N; ++ i) F[T][T][i][0] = F[T][T][i][1] = 0;
	
	for (int len = 2; len <= N; ++ len) {
		for (int l = 1; l + len - 1 <= N; ++ l) {
			r = l + len - 1;
			for (int k = 0; k < min (N, l + N - r); ++ k) {
				F[l][r][k][0] = max ({F[l + 1][r][k][0] - 1ll * k * Dis (l, l + 1), F[l + 1][r][k][1] - 1ll * k * Dis (l, r), F[l + 1][r][k + 1][0] - 1ll * (k + 1) * Dis (l, l + 1) + C[l].l, F[l + 1][r][k + 1][1] - 1ll * (k + 1) * Dis (l, r) + C[l].l});
				F[l][r][k][1] = max ({F[l][r - 1][k][0] - 1ll * k * Dis (l, r), F[l][r - 1][k][1] - 1ll * k * Dis (r - 1, r), F[l][r - 1][k + 1][0] - 1ll * (k + 1) * Dis (l, r) + C[r].l, F[l][r - 1][k + 1][1] - 1ll * (k + 1) * Dis (r - 1, r) + C[r].l});
			}
		}
	}
	
	cout << max (F[1][N][0][0], F[1][N][0][1]) << endl;
	
	return 0;
}

而由于我们这里数组有 300×300×300×2=5.4×107 的大小,还是 long long

所以其 访问速度 差到了极致,慢的飞起

但由于这是 区间 DP,我们注意到 len 单调变化,并且右端点 r 可以通过 l+len1 唯一表示

所以我们可以 省掉一个维度,每次 ++ len 的时候 滚动更新

#include <bits/stdc++.h>

const int MAXN = 305;

using namespace std;

long long G[MAXN][MAXN][2], Z[MAXN][MAXN][2];

struct Candle {
	int x, l;
	inline bool operator < (const Candle &a) const {
		return x < a.x;
	}
} C[MAXN];

inline long long Dis (const int L, const int R) {
	return 0ll + C[R].x - C[L].x;
}

int N, T, r, t;

signed main () {
	
	cin >> N;
	
	for (int i = 1; i <= N; ++ i) cin >> C[i].x >> C[i].l;
	
	C[++ N] = {0, 0};
	
	sort (C + 1, C + N + 1);
	
	for (int i = 1; i <= N; ++ i) if (!C[i].l) {T = i; break ;}
	
	memset (Z, -127, sizeof Z);
	memset (G, -127, sizeof G);
	
	for (int i = 0; i <= N; ++ i) Z[T][i][0] = Z[T][i][1] = G[T][i][0] = G[T][i][1] = 0;
	
	for (int len = 2; len <= N; ++ len) {
		for (int l = 1; l + len - 1 <= N; ++ l) {
			r = l + len - 1, t = l + N - r;
			for (int k = 0; k < min (N, t); ++ k) {
				G[l][k][0] = max ({Z[l + 1][k][0] - 1ll * k * Dis (l, l + 1), Z[l + 1][k][1] - 1ll * k * Dis (l, r), Z[l + 1][k + 1][0] - 1ll * (k + 1) * Dis (l, l + 1) + C[l].l, Z[l + 1][k + 1][1] - 1ll * (k + 1) * Dis (l, r) + C[l].l});
				G[l][k][1] = max ({Z[l + 0][k][0] - 1ll * k * Dis (l, r), Z[l + 0][k][1] - 1ll * k * Dis (r - 1, r), Z[l + 0][k + 1][0] - 1ll * (k + 1) * Dis (l, r) + C[r].l, Z[l + 0][k + 1][1] - 1ll * (k + 1) * Dis (r - 1, r) + C[r].l});
			}
		}
		memcpy (Z, G, sizeof G);
	}
	
	cout << max (G[1][0][0], G[1][0][1]) << endl;
	
	return 0;
}
posted @   FAKUMARER  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示