您的位置:首页 > 其它

关路灯_洛谷1220_dp

2017-01-15 20:36 204 查看

题目描述

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

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

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

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

输入格式:

文件第一行是两个数字n(0

输出格式:

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

Solution’

这题好劲a,1A大法好

首先读懂题目,这位大爷显然是只能关与当前位置相邻的灯的,那么就又变成了一段数字从两端取的模型,不同的是这是从中间往两边罢了

注意到题目的不同,我们的方程也要改。f[i][j][0] 表示i至j之间的灯都关上了,且当前大爷在i的位置上,f[i][j][1] 表示关灯后我们的大爷在j的位置

一开始的想法是既然要找最小功耗,那么是不是可以变成最大节省的功?显然是不行的,因为时间是未知的。我们可以用总的功率减去已经关上的灯i至j的功率计算功耗

还有就是,我们的大爷足够聪明,即他不会从最左边走去关最右边的灯再走回最左边,也不会从最右边走向最左边关掉灯然后走回去,也就是f[i][j][0]只能从f[i+1][j][0或1]转移,另一边同理

转移显然

f[i][j][0]=min(f[i+1][j][0]+dis(i,i+1)∗∑t=i+1t<=jp[t],f[i+1][j][1]+dis(i,j)∗∑t=i+1t<=jp[t])

f[i][j][1]=min(f[i][j−1][0]+dis(i,j)∗∑t=it<=j−1p[t],f[i][j−1][1]+dis(j−1,j)∗∑t=i+1t<=j−1p[t])

其中dis(i,j)表示路灯间的距离

Code

#include <stdio.h>
#include <string.h>
#include <math.h>
#define rep(i, a, b) for (int i = a; i <= b; i ++)
#define fill(x, t) memset(x, t ,sizeof(x))
#define N 101
using namespace std;
int f

[2], p
, dis
, sum
, t
;
inline int read(){
int x = 0, v = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-'){
v = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * v;
}
inline int min(int x, int y){
return x<y?x:y;
}
inline int cal(int i, int j){
return fabs(sum[j] - sum[i - 1]);
}
inline int dist(int i, int j){
return fabs(dis[j] - dis[i]);
}
int main(void){
int n = read(), st = read();
rep(i, 1, n){
t[i] = read();
p[i] = read();
dis[i] = dis[i - 1] + t[i] - t[i - 1];
sum[i] = sum[i - 1] + p[i];
}
fill(f, 63);
f[st][st][0] = f[st][st][1] = 0;
for (int i = st; i >= 1; i --){
for (int j = st; j <= n; j ++){
f[i][j][0] = min(f[i][j][0], f[i + 1][j][0] + dist(i + 1, i) * (sum
- cal(i + 1, j)));
f[i][j][0] = min(f[i][j][0], f[i + 1][j][1] + dist(j, i) * (sum
- cal(i + 1, j)));
f[i][j][1] = min(f[i][j][1], f[i][j - 1][0] + dist(j, i) * (sum
- cal(i, j - 1)));
f[i][j][1] = min(f[i][j][1], f[i][j - 1][1] + dist(j, j - 1) * (sum
- cal(i, j - 1)));
}
}
printf("%d\n", min(f[1]
[0], f[1]
[1]));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: