ABC219H Candles
[ABC219H] Candles
很像 关路灯 这玩意儿啊,容易想到区间
仿照那道题,可以考虑设出状态,即 当前已经熄掉的区间
我们有如下转移
但是这题的区别就在于 蜡烛是会熄灭的
也就是如果按 上式转移,当发生蜡烛已经熄灭时人才到位的情况时,贡献会错
于是我们可以考虑 多设一种状态,用
每次的转移我们考虑 这个蜡烛是否已经熄灭,换言之就是 是否要被熄灭
-
如果其已经熄灭,即 它不用被熄灭(之后还需熄灭的蜡烛不变,故从
转移过来)则
将从 中 转移,且 不会加上这个蜡烛的贡献而
将从 中 转移,且 不会加上这个蜡烛的贡献 -
如果其还没熄灭,即 现在把它熄灭(之后还需熄灭的蜡烛
,故从 转移过来)则
将从 中 转移,且 应当加上这个蜡烛的贡献而
将从 中 转移,且 应当加上这个蜡烛的贡献
而由于我们当前有
故我们的 花费(
于是最终转移式如下
然后我们可以写出这样的代码
注意到 剩余需要熄灭的蜡烛 不可能比 剩余蜡烛 多,所以枚举
的时候可以 适当剪枝,见下
#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;
}
而由于我们这里数组有 long long
所以其 访问速度 差到了极致,慢的飞起
但由于这是 区间 len
单调变化,并且右端点
所以我们可以 省掉一个维度,每次 ++ 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话