news 2026/10/12 5:38:53

P1220 关路灯【洛谷算法习题】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P1220 关路灯【洛谷算法习题】

P1220 关路灯

网页链接

P1220 关路灯

题目描述

某一村庄在一条路线上安装了n nn盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少)。老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯。

为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能够最节省电。他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯。开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择先关掉功率大的一边,再回过头来关掉另一边的路灯,而事实并非如此,因为在关的过程中适当地调头有可能会更省一些。

现在已知老张走的速度为1 m / s 1m/s1m/s,每个路灯的位置(是一个整数,即距路线起点的距离,单位:m mm)、功率(W WW),老张关灯所用的时间很短而可以忽略不计。

请你为老张编一程序来安排关灯的顺序,使从老张开始关灯时刻算起所有灯消耗电最少(灯关掉后便不再消耗电了)。

输入格式

第一行是两个数字n nn(表示路灯的总数)和c cc(老张所处位置的路灯号);

接下来n nn行,每行两个数据,表示第1 11盏到第n nn盏路灯的位置和功率。数据保证路灯位置单调递增。

输出格式

一个数据,即最少的功耗(单位:J JJ,1 J = 1 W × s 1J=1W\times s1J=1W×s)。

输入输出样例 #1

输入 #1

5 3 2 10 3 20 5 20 6 30 8 10

输出 #1

270

说明/提示

样例解释

此时关灯顺序为3 4 2 1 5。

数据范围

1 ≤ n ≤ 50 1\le n\le501≤n≤50,1 ≤ c ≤ n 1\le c\le n1≤c≤n,1 ≤ W i ≤ 100 1\le W_i \le 1001≤Wi​≤100,1 ≤ 路灯位置 ≤ 100 1 \leq \text{路灯位置} \leq 1001≤路灯位置≤100

解题思路

解题思路

本题是区间动态规划的经典问题。老张关灯的过程可以看作是在一条直线上不断扩展已关灯的连续区间,因此可以用区间 DP 来求解最小功耗。

1. 问题等价转化
  • 路灯按位置升序排列,老张从第c cc盏灯出发,每次关掉一盏灯。由于他只会走向相邻的未关路灯,因此任意时刻已经关掉的路灯必然构成一个连续的区间[ i , j ] [i, j][i,j]。
  • 老张关灯后可能停在区间的左端点i ii或右端点j jj,因此需要两个状态来区分。
  • 功耗 = 时间 × 功率。老张行走速度为1 m/s 1\,\text{m/s}1m/s,所以行走时间等于行走距离。在行走过程中,所有尚未关掉的路灯仍在耗电。因此,每次移动的功耗 = 移动距离 × 当前未关路灯的总功率。
2. 动态规划设计
  • 状态定义:
    • F[i][j][0]:关掉区间[ i , j ] [i, j][i,j]的所有路灯后,老张停在左端点i ii时的最小总功耗。
    • F[i][j][1]:关掉区间[ i , j ] [i, j][i,j]的所有路灯后,老张停在右端点j jj时的最小总功耗。
  • 前缀和:S[i]表示前i ii盏灯的总功率。关掉区间[ i , j ] [i, j][i,j]后,未关路灯包括[ 1 , i − 1 ] [1, i-1][1,i−1]和[ j + 1 , n ] [j+1, n][j+1,n],其总功率为:
    rem ( i , j ) = S [ i − 1 ] + S [ n ] − S [ j ] \text{rem}(i, j) = S[i-1] + S[n] - S[j]rem(i,j)=S[i−1]+S[n]−S[j]
    但在转移过程中,需要注意移动时目标灯尚未关掉,因此计算功耗时未关灯的总功率应包含目标灯。例如从i + 1 i+1i+1走到i ii时,此时i ii还未关,所以未关灯总功率为S [ i ] + S [ n ] − S [ j ] S[i] + S[n] - S[j]S[i]+S[n]−S[j](因为[ i + 1 , j ] [i+1, j][i+1,j]已关)。
  • 转移方程(区间长度len从2 22到n nn):
    • 对于区间[ i , j ] [i, j][i,j](j = i + l e n − 1 j = i + len - 1j=i+len−1),考虑最后一步:
      • 若最后停在i ii,则上一步可能停在i + 1 i+1i+1(从i + 1 i+1i+1向左走到i ii)或停在j jj(从j jj一路向左走到i ii):
        F [ i ] [ j ] [ 0 ] = min ⁡ { F [ i + 1 ] [ j ] [ 0 ] + ( X [ i + 1 ] − X [ i ] ) × ( S [ i ] + S [ n ] − S [ j ] ) F [ i + 1 ] [ j ] [ 1 ] + ( X [ j ] − X [ i ] ) × ( S [ i ] + S [ n ] − S [ j ] ) F[i][j][0] = \min \begin{cases} F[i+1][j][0] + (X[i+1] - X[i]) \times (S[i] + S[n] - S[j]) \\ F[i+1][j][1] + (X[j] - X[i]) \times (S[i] + S[n] - S[j]) \end{cases}F[i][j][0]=min{F[i+1][j][0]+(X[i+1]−X[i])×(S[i]+S[n]−S[j])F[i+1][j][1]+(X[j]−X[i])×(S[i]+S[n]−S[j])​
      • 若最后停在j jj,则上一步可能停在j − 1 j-1j−1(从j − 1 j-1j−1向右走到j jj)或停在i ii(从i ii一路向右走到j jj):
        F [ i ] [ j ] [ 1 ] = min ⁡ { F [ i ] [ j − 1 ] [ 0 ] + ( X [ j ] − X [ i ] ) × ( S [ i − 1 ] + S [ n ] − S [ j − 1 ] ) F [ i ] [ j − 1 ] [ 1 ] + ( X [ j ] − X [ j − 1 ] ) × ( S [ i − 1 ] + S [ n ] − S [ j − 1 ] ) F[i][j][1] = \min \begin{cases} F[i][j-1][0] + (X[j] - X[i]) \times (S[i-1] + S[n] - S[j-1]) \\ F[i][j-1][1] + (X[j] - X[j-1]) \times (S[i-1] + S[n] - S[j-1]) \end{cases}F[i][j][1]=min{F[i][j−1][0]+(X[j]−X[i])×(S[i−1]+S[n]−S[j−1])F[i][j−1][1]+(X[j]−X[j−1])×(S[i−1]+S[n]−S[j−1])​
        注意:在计算F[i][j][0]时,未关灯总功率为S [ i ] + S [ n ] − S [ j ] S[i] + S[n] - S[j]S[i]+S[n]−S[j];在计算F[i][j][1]时,未关灯总功率为S [ i − 1 ] + S [ n ] − S [ j − 1 ] S[i-1] + S[n] - S[j-1]S[i−1]+S[n]−S[j−1]。这是因为移动的目标灯不同,目标灯在到达前尚未关掉。
  • 边界条件:
    • 初始状态:F[c][c][0] = F[c][c][1] = 0(只有第c cc盏灯被关,老张就在该位置)。
    • 其他所有F初始化为一个极大值(代码中用memset(F, 127, sizeof(F))实现,即将每个字节设为0x7f,对long long而言是一个很大的数)。
  • 最终答案:min(F[1][n][0], F[1][n][1]),即关掉所有灯后,无论老张停在左端还是右端的最小功耗。
3. 复杂度分析
  • 时间复杂度:状态数为O ( n 2 ) O(n^2)O(n2),每个状态转移O ( 1 ) O(1)O(1),总时间复杂度O ( n 2 ) O(n^2)O(n2)。n ≤ 50 n \le 50n≤50,运算量极小。
  • 空间复杂度:需要存储三维 DP 数组F[60][60][2]以及位置、功率、前缀和数组,空间复杂度O ( n 2 ) O(n^2)O(n2),完全可接受。

总结

将关灯过程建模为区间扩展,用两个状态分别表示老张停在区间左端或右端。转移时考虑从相邻区间扩展而来,并乘以当前未关路灯的总功率(即剩余灯仍在耗电)。通过前缀和快速计算未关灯总功率,实现O ( 1 ) O(1)O(1)转移。该方法思路清晰,是区间 DP 在资源调度类问题中的典型应用。

代码内容

#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'typedeflonglongll;typedefunsignedlonglongull;typedefvector<vector<ll>>vvt;typedefpair<ll,ll>pll;constll N=1e3+10;constll INF=1e18;constll M=1e6+10;constll mod=1e9+7;constll MAXM=60;ll X[MAXM],Y[MAXM],S[MAXM],n,c;ll F[MAXM][MAXM][2];intmain(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);scanf("%lld%lld",&n,&c);memset(F,127,sizeof(F));for(ll i=1;i<=n;i++){scanf("%lld%lld",&X[i],&Y[i]);S[i]=S[i-1]+Y[i];}F[c][c][0]=F[c][c][1]=0;for(ll len=2;len<=n;len++){for(ll i=1;i+len-1<=n;i++){ll j=i+len-1;F[i][j][0]=min(F[i+1][j][0]+(X[i+1]-X[i])*(S[i]+S[n]-S[j]),F[i+1][j][1]+(X[j]-X[i])*(S[i]+S[n]-S[j]));F[i][j][1]=min(F[i][j-1][0]+(X[j]-X[i])*(S[i-1]+S[n]-S[j-1]),F[i][j-1][1]+(X[j]-X[j-1])*(S[i-1]+S[n]-S[j-1]));}}ll ans=min(F[1][n][0],F[1][n][1]);printf("%lld",ans);return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 5:37:55

基于Matlab/Simulink的有源电力滤波器APF仿真模型搭建与谐波治理指南

最近有个朋友拿着一张电能质量测试报告来找我&#xff0c;说厂里几台直流充电设备一开&#xff0c;进线电流总谐波畸变率直接飙到27%&#xff0c;不仅电容器柜里嗡嗡响&#xff0c;还偶尔触发保护误动。我一看波形&#xff0c;典型的“不控整流大电感直流侧”经典电流方波。我给…

作者头像 李华
网站建设 2026/10/12 5:37:27

从游戏整理到备份恢复:AnyPS5让PS5内容管理更高效

你有没有遇到过这样的情况&#xff1a;PS5买回来头一个月恨不得天天开机&#xff0c;游戏也囤了不少&#xff0c;等游戏热潮一过&#xff0c;就是“开机不知道玩什么&#xff0c;关机又觉得亏”。我自己的机器就是这么吃灰的&#xff0c;直到后来我决定不折腾硬件&#xff0c;只…

作者头像 李华
网站建设 2026/10/12 5:36:47

ArchLinux(二):图形界面美化(KDE Plasma)

前置操作 设置yay仓库 配置 archlinuxcn 源&#xff1b;这能让 pacman 直接从国内镜像下载预编译包&#xff0c;速度快很多。 编辑文件 /etc/pacman.conf 在最后添加上如下内容 [archlinuxcn] SigLevel Optional TrustedOnly Server https://mirrors.tuna.tsinghua.edu.cn/ar…

作者头像 李华
网站建设 2026/10/12 5:36:41

ShK Toxin;172450-46-3

基本性质中文名称&#xff1a;ShK 毒素&#xff0c;海葵 ShK 钾通道毒素CAS 号&#xff1a;172450-46-3单字母序列&#xff1a;RSCIDTIPKSRCTAFQCKHSMKYRLSFCRKTCGTC三字母序列&#xff1a;Arg-Ser-Cys-Ile-Asp-Thr-Ile-Pro-Lys-Ser-Arg-Cys-Thr-Ala-Phe-Gln-Cys-Lys-His-Ser-M…

作者头像 李华
网站建设 2026/10/12 5:35:02

MyBatis <sql>标签深度解析:从原理到面试

1. 先看一段重复到想吐的SQL&#xff1a;这个标签存在的理由后端开发做到三五年&#xff0c;面试桌上大概率会被问起 MyBatis。其他题多少能聊几句&#xff0c;唯独这种"看着很简单"的标签题&#xff0c;最容易暴露你是背过答案还是真在项目里用过。我见过不少候选人…

作者头像 李华