链接:https://www.nowcoder.com/acm/contest/93/J
来源:牛客网
我国现在能源消耗非常严重,现在政府有这样一个工作,每天早上都需要把一些路灯关掉,但是他们想让在关闭的过程中所消耗的能源是最少的,负责路灯关闭的工作人员以1m/s的速度进行行走,假设关闭路灯的时候不需要花费任何的时间,请你编写一个程序,计算在给定路灯位置和每个路灯的消耗能源的多少,求出当所有路灯关闭的时候所需要的最少能量
一开始,起点s处路灯一定可以关,其余路灯位于s两侧,人不断向左右走去关灯,保证了一个包含s的区间[ i , j ],使得路灯i到路灯j区间内的路灯一定是熄灭的。
即一开始路灯熄灭区间为[ s , s ],后来不断向左向右扩大。
//dp[i][j][0]表示[路灯i,路灯j]内路灯全部熄灭,且站在i处时,的消耗掉最小能量
区间[i][j][0]是由[i + 1][j]从左边i + 1处dp[i + 1][j][0])向左走一步达到i,或者是由[i + 1][j][1]从右边j处(dp[i + 1][j][1])走到i
计算走的时间,乘除了区间[i + 1][j]已经熄灭的灯外,其他灯在这段时间内消耗的能量。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1e3 + 5;
const int INF = 0X3f3f3f3f;
int d[maxn],w[maxn];
int dp[maxn][maxn][2];//dp[i][j][0]表示[路灯i,路灯j]内路灯全部熄灭,且站在i处时,的消耗掉最小能量
int sum = 0;
int n,s;
int main()
{
while (scanf("%d",&n) != EOF) {
scanf("%d",&s);
sum = 0;
for (int i = 1; i <= n; i ++) {
scanf("%d%d",&d[i],&w[i]);
sum += w[i];
w[i] += w[i - 1];
}
memset(dp, 0x3f, sizeof(dp));
dp[s][s][0] = dp[s][s][1] = 0;
//递推顺序应该从s向2边推
for (int i = s; i >= 1; i --) {
for (int j = s ; j <= n; j ++) {
if(i == s && j == s) continue;
dp[i][j][0] = min(dp[i + 1][j][0] + (d[i + 1] - d[i]) * (sum - w[j] + w[i]),
dp[i + 1][j][1] + (d[j] - d[i]) * (sum - w[j] + w[i]));
dp[i][j][1] = min(dp[i][j - 1][1] + (d[j] - d[j - 1]) * (sum - w[j - 1] + w[i - 1]),
dp[i][j - 1][0] + (d[j] - d[i]) * (sum - w[j -1] + w[i - 1]));
}
}
printf("%d\n",min(dp[1][n][0],dp[1][n][1]));
}
return 0;
}