关路灯_洛谷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; }
相关文章推荐
- 【洛谷1220】关路灯
- [luoguP1220] 关路灯(DP)
- 爆搜+记忆化(洛谷1220 关路灯)
- [区间dp] 洛谷 P1220 关路灯
- 【DP】洛谷 P1220 关路灯
- 洛谷1220 关路灯
- 【CJOJ1603】【洛谷1220】关路灯
- 洛谷 P1220 关路灯 (区间DP)
- 洛谷 2409 dp 月赛题目
- 洛谷 1063 dp 区间dp
- 洛谷 1156 dp
- 洛谷 1052 dp 状态压缩
- 洛谷 1373 dp 小a和uim之大逃离 良心题解
- 【洛谷】[ZJOI2007]时态同步-树形DP
- [Poj1717]&[洛谷1282]多米诺骨牌 背包Dp
- dp的开关路灯
- UVA 1220 树形dp 最大独立集+状态标记
- DP【洛谷P4290】 [HAOI2008]玩具取名
- 洛谷 P2831 愤怒的小鸟(状压dp)
- UVA 1220 树形dp