专栏文章
P1220 关路灯 题解
题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minkhmo1
- 此快照首次捕获于
- 2025/12/02 03:53 3 个月前
- 此快照最后确认于
- 2025/12/02 03:53 3 个月前
题目大意
一条直线上有 盏路灯,第 盏灯的位置为 (单位:米),功率为 (单位:瓦)。老张初始位于第 盏灯处,他需要关闭所有灯。他的行走速度为 ,关灯时间忽略不计。
每盏灯在被关闭前持续耗电,目标是安排关灯顺序,使得从开始关灯时刻起,所有灯消耗的总电能(单位:焦耳)最小。
解题思路
1. 问题转化
- 总耗电量 = 每盏灯的功率 它被关闭前所经过的时间。
- 时间 = 老张走过的路径长度(速度为 )。
2. 区间 DP 的适用性
观察发现:
- 老张关灯的过程一定是从初始位置 开始,逐步向左或向右扩展已关灯的连续区间。
- 一旦区间 内的灯全部关闭,老张必定位于 或 。
- 后续只能关 或 。
这符合区间动态规划的典型特征。
3. 状态定义
定义:
- :关闭区间 内所有灯,且当前位于 左端点 时,已产生的最小总耗电量;
- :关闭区间 内所有灯,且当前位于 右端点 时的最小总耗电量。
4. 前缀和优化
设 ,即功率前缀和。
则任意区间外的总功率可快速计算:
- 区间 之外的灯总功率为:
5. 状态转移
转移到左端点
从 扩展而来:
- 若原在 :走 ;
- 若原在 :走 。
未关灯为 ,总功率为 。
故:
转移到右端点
从 扩展而来:
- 若原在 :走 ;
- 若原在 :走 。
未关灯为 ,总功率为 。
故:
6. 初始状态与答案
- 初始:;
- 其余状态初始化为 ;
- 最终答案:。
代码实现
CPP#include <bits/stdc++.h>
using namespace std;
int n /*路灯总数*/, c /*初始位置*/;
int wz[51] /*路灯位置*/, gl[51] /*功率*/;
int gl_qzh[51] /*功率的前缀和*/;
int f[51][51][2];
// f[i][j][0] 表示关闭从 i 到 j 的灯,现在在 i 处的总功率
// f[i][j][1] 表示关闭从 i 到 j 的灯,现在在 j 处的总功率
int main()
{
cin >> n >> c;
for (int i = 1; i <= n; ++i)
cin >> wz[i] >> gl[i];
for (int i = 1; i <= n; ++i)
gl_qzh[i] = gl_qzh[i - 1] + gl[i];
memset(f, 0x3f, sizeof(f)); // 初始为最大值
f[c][c][0] = f[c][c][1] = 0; // 初始位置
for (int l = 1; l <= n; ++l) // 枚举区间长度
for (int i = 1; i <= n - l; ++i) // 枚举起点
{
int j = i + l; // 终点
f[i][j][0] = min // 去 i 处
(
f[i + 1][j][0] + // 从 i + 1 处出发
(gl_qzh[i] + (gl_qzh[n] - gl_qzh[j])) /*[1, i] ∪ (j, n]*/ * (wz[i + 1] - wz[i]) /*距离*/,
f[i + 1][j][1] + // 从 j 处出发
(gl_qzh[i] + (gl_qzh[n] - gl_qzh[j])) /*[1, i] ∪ (j, n]*/ * (wz[j] - wz[i]) /*距离*/
);
f[i][j][1] = min // 在 j 处
(
f[i][j - 1][0] + // 从 i 处出发
(gl_qzh[i - 1] + (gl_qzh[n] - gl_qzh[j - 1])) /*[1, i) ∪ [j, n]*/ * (wz[j] - wz[i]) /*距离*/,
f[i][j - 1][1] + // 从 j - 1 处出发
(gl_qzh[i - 1] + (gl_qzh[n] - gl_qzh[j - 1])) /*[1, i) ∪ [j, n]*/ * (wz[j] - wz[j - 1]) /*距离*/
);
}
cout << min(f[1][n][0], f[1][n][1]) << '\n';
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...