题目
题目描述
我国现在能源消耗非常严重,现在政府有这样一个工作,每天早上都需要把一些路灯关掉,但是他们想让在关闭的过程中所消耗的能源是最少的,负责路灯关闭的工作人员以1m/s的速度进行行走,假设关闭路灯的时候不需要花费任何的时间,请你编写一个程序,计算在给定路灯位置和每个路灯的消耗能源的多少,求出当所有路灯关闭的时候所需要的最少能量
输入描述
多组测试数据循环输入
每组测试数据第一行:N表示路灯的数量 (2<=N <=1000)
第二行:V表示开始关灯的路灯号码。 (1<=V<=N)
接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每盏灯的参数
D表示该路灯到原点的距离 (用米为单位来表示),
W表示灯泡的功率,即每秒该灯泡所消耗的能量数。(0<=D<=1000,0<=W<=1000)
路灯按照顺序给出,起始位置的那盏灯不算消耗的电能里面
输出描述
输出一个整数,即消耗能量之和的最小值。
示例1
输入
4
3
2 2
5 8
6 1
8 7
输出
56
说明
对于样例,我一开始在第三个路灯的位置,即在6位置
第1s的时候去5把第二盏灯关闭,消耗电能8
然后去第四盏灯,第四盏灯亮的时间是4s 所以消耗电能28
最后去关第一盏灯第一盏灯亮的时间是10s 所以消耗电能20
最后总和为8+28+20=56
题解
知识点:区间dp。
先给出一个贪心的结论,下一个关的灯一定是距离最近的没关的灯,那么最后发现下一个关的灯其实就是区间的左右端点,于是可以区间dp。但注意,因为有从左到右选右端点,或者回到左端点选左端点,也有从右到左选左端点,或者回到右端点选右端点,具体转移方程看代码。
时间复杂度 \(O(nv)\)
空间复杂度 \(O(n^2)\)
代码
#include <bits/stdc++.h>
using namespace std;
int dp[1007][1007];
int d[1007], w[1007], sum[1007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
while (cin >> n) {
int v;
cin >> v;
for (int i = 1;i <= n;i++) {
cin >> d[i] >> w[i];
sum[i] = sum[i - 1] + w[i];
}
memset(dp, 0x3f, sizeof(dp));
dp[v][v] = 0;
///起点确定直接推,不需要区间长度循环
for (int l = v;l >= 1;l--) {
for (int r = l + 1;r <= n;r++) {
dp[l][r] =
min(
dp[l][r - 1] + (d[r] - d[r - 1]) * (sum[n] - (sum[r - 1] - sum[l - 1])),
dp[r - 1][l] + (d[r] - d[l]) * (sum[n] - (sum[r - 1] - sum[l - 1]))
);
dp[r][l] =
min(
dp[r][l + 1] + (d[l + 1] - d[l]) * (sum[n] - (sum[r] - sum[l])),
dp[l + 1][r] + (d[r] - d[l]) * (sum[n] - (sum[r] - sum[l]))
);
}
}
cout << min(dp[1][n], dp[n][1]) << '\n';
}
return 0;
}
标签:路灯,int,消耗,问题,NC15447,端点,1007,dp,wyh
From: https://www.cnblogs.com/BlankYang/p/16586870.html