题目描述

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

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

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

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

输入格式

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

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

输出格式

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

输入输出样例

输入 #1

5 3

2 10

3 20

5 20

6 30

8 10

输出 #1

270

说明/提示

样例解释

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

数据范围

\(1≤n≤50,1≤c≤n\)

分析

这个题从题目的意思,应该挺容易就能看出来是一个区间\(dp\),因为题意就是一个大爷在一个“区间”里关灯。所以就可以根据区间长度来进行状态转移。首先想到如果大爷关灯从\(i\)到\(j\),当然这并不代表关灯顺序,大爷关灯肯定是走过的路上的灯都关了,因为这肯定比走过不关再回来关要优。而在\(i\)到\(j\)这一段关了灯的区间里,大爷有两种位置情况,一种是在\(i\),也就是左边,另一种就是右边,所以我们的dp数组就可以根据这个来开,也就是\(dp[i][j][0]\)和\(dp[i][j][1]\)分别表示关了i,j之间的灯,然后在最左和最右两种位置的情况,而区间长度肯定是从最短到最长,最短为1,然后依次增加,所以每一次的\(dp[i][j]\)的状态都是从上一个转移下来的,也就是\(dp[i+1][j]\)和$dp[i][j-1],然后分别在左右端点两种,依次进行状态转移。而能耗的增量可以通过时间和区间里能耗的前缀和来进行转移,下边我用一个转移方程来进行一下具体说明:

首先是个转移方程:

\[dp[i][j][0] = min(dp[i+1][j][0]+(pos[i+1] - pos[i])\times sum[i+1][j],dp[i+1][j][1]+(pos[j]-pos[i])\times sum[i+1][j])
\]

在这里,\(pos\)代表位置(这里的位置说的是下标,不是距离,但是pos数组存的是距离,用来计算时间)\(sum\)数组代表的是从\(i\)到\(j\)之外的能耗,\(sum\)需要一个预处理,下边单独说,这里先介绍含义,方便理解。这个状态转移方程的意思也就是\(i\)到\(j\)区间内,大爷在左边的时候,通过不同的上个状态的位置来进行转移,值得一提的是,因为此时大爷在左边界,所以肯定是由\(dp[i+1][j]\)转移而来,假如是由\(dp[i][j-1]\)转移来的话,应当在右侧,这就是下一个状态转移方程。继续看这个方程,从\(dp[i+1][j]\)转移而来,所以也有两种,左右边界各一种,在左边界时,他所需的时间就是\(pos[i+1] - pos[i]\),右边界时就是\(pos[j]-pos[i]\),而花费的功率就是sum乘以时间,分别为:\((pos[i+1] - pos[i])\times sum[i+1][j]\)和\((pos[j]-pos[i])\times sum[i+1][j]\),看到这里可能有人会有疑惑,从\(i\)到\(j\)之外的能耗为啥是\(i+1\)到\(j\)呢,现在我们来说一下\(sum\)的得出:我们先用\(val\)数组当做前缀和,区间\(i\)到\(j\)的能耗就是\(val[j]-val[i-1]\),\(sum[i][j]\)就是用\(val[n]\)减去上边的能耗,具体见代码。现在大概就都解释清楚了。然后就是两个关键的状态转移方程:

\[dp[i][j][0] = min(dp[i+1][j][0]+(pos[i+1] - pos[i])*sum[i+1][j],dp[i+1][j][1]+(pos[j]-pos[i])*sum[i+1][j]) \\
dp[i][j][1] = min(dp[i][j-1][1]+(pos[j]-pos[j-1])*sum[i][j-1],dp[i][j-1][0]+(pos[j]-pos[i])*sum[i][j-1])\]

就这样了,然后看一下代码加深一下理解⑧

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 55;
int pos[maxn];
int sum[maxn][maxn];
int dp[maxn][maxn][3];
int v[maxn];
int n,c;
int main(){
cin>>n>>c;
for(int i=1;i<=n;++i){
int w;
cin>>pos[i]>>w;
v[i]=v[i-1]+w;
}
memset(dp,0x3f,sizeof(dp));
dp[c][c][0] = dp[c][c][1] = 0;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
sum[i][j] = v[n] - (v[j] - v[i-1]);
}
}
for(int j = c;j<=n;++j){
for(int i=j-1;i>=1;--i){
dp[i][j][0] = min(dp[i+1][j][0]+(pos[i+1] - pos[i])*sum[i+1][j],dp[i+1][j][1]+(pos[j]-pos[i])*sum[i+1][j]);
dp[i][j][1] = min(dp[i][j-1][1]+(pos[j]-pos[j-1])*sum[i][j-1],dp[i][j-1][0]+(pos[j]-pos[i])*sum[i][j-1]);
}
}
int ans = min(dp[1][n][0],dp[1][n][1]);
cout<<ans<<endl;
}

洛谷P1220关路灯【区间dp】的更多相关文章

  1. 洛谷 P1220 关路灯 区间DP

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

  2. 洛谷P1220关路灯——区间DP

    题目:https://www.luogu.org/problemnew/show/P1220 区间DP. 代码如下: #include<iostream> #include<cstd ...

  3. 洛谷P1220关路灯[区间DP]

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

  4. 洛谷P1220关路灯[区间DP 提前计算代价]

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

  5. 洛谷 P1220 关路灯 题解

    Description 有 $n$ 盏路灯,每盏路灯有坐标(单位 $m$)和功率(单位 $J$).从第 $c$ 盏路灯开始,可以向左或向右关闭路灯.速度是 $1m/s$.求所有路灯的最少耗电.输入保证 ...

  6. 洛谷P1220 关路灯

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

  7. P1220 关路灯——区间dp

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

  8. 洛谷——P1220 关路灯

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

  9. 洛谷P1220 关路灯 题解 区间DP

    题目链接:https://www.luogu.com.cn/problem/P1220 本题涉及算法:区间DP. 我们一开始要做一些初始化操作,令: \(p[i]\) 表示第i个路灯的位置: \(w[ ...

  10. 洛谷P1220 关路灯【区间dp】

    题目:https://www.luogu.org/problemnew/show/P1220 题意:给定n盏灯的位置和功率,初始时站在第c盏处. 关灯不需要时间,走的速度是1单位/秒.问把所有的灯关掉 ...

随机推荐

  1. ASP.NET通过更改Url进行页面传值

    这里,通过假数据,手动创建的一个类,然后创建的一个集合,放入下拉框,选好值以后,点确定 会在另一个页面产生对应的id,有不懂的欢迎评论 创建一个类: using System; using Syste ...

  2. Java实现 蓝桥杯 算法提高 矩阵乘法(暴力)

    试题 算法提高 矩阵乘法 问题描述 小明最近刚刚学习了矩阵乘法,但是他计算的速度太慢,于是他希望你能帮他写一个矩阵乘法的运算器. 输入格式 输入的第一行包含三个正整数N,M,K,表示一个NM的矩阵乘以 ...

  3. Java实现 LeetCode 715 Range 模块(选范围)

    715. Range 模块 Range 模块是跟踪数字范围的模块.你的任务是以一种有效的方式设计和实现以下接口. addRange(int left, int right) 添加半开区间 [left, ...

  4. MySQL基本DML

    DML: 数据操纵语言, 主要用来向数据库中添加. 删除. 修改数据用的.在开发中经常会用到,所以,在此也小小总结一下: CREATE DATABASE db2 DEFAULT CHARSET UTF ...

  5. vscode的个人配置

    前言 此篇只是为了记录自己vscode的设置,防止以后配置丢失,无实际意义 { "files.autoSave": "afterDelay", "ed ...

  6. (四)rsync未授权访问

    01 漏洞描述 rsync是Linux/Unix下的一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件和目录,默认运行在873端口.由于配置不当,导致任何人可未授权访问rsync,上传 ...

  7. cuda基础

    一:cuda编程模型 1:主机与设备 主机---CPU 设备/处理器---GPU CUDA编程模型如下: GPU多层存储空间结构如图: 2:Kernel函数的定义与调用 A:运行在GPU上,必须通过_ ...

  8. WPF 学习(一)

    一.WPF介绍 WPF全称 Windows Presentation Foundation,干啥用的? 主要是用来制作Windows桌面客户端软件的. .Net平台下制作Windows桌面客户端软件主 ...

  9. linux下的mysql目录

    /usr/bin 客户端程序和脚本[root@~ bin]# ls mysql*mysql mysqldump mysql_secure_installationmysqladmin mysqldum ...

  10. (数据科学学习手札87)利用adjustText解决matplotlib文字标签遮挡问题

    本文示例代码.数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在进行数据可视化时我们常常需要在可视化作品 ...