# Solution

$dp_{i, j}$表示修缮完区间$[i, j]$后的时间内再修其它区间产生的花费。

$s_i$表示区间$[1, i]$内的$\Delta$的和，$len_{i, j}$表示点$i$到点$j$的距离。很容易的列出$dp$式子：

$cost = s_n - (s_j - s_{i - 1})$

$dp_{i, j, 0} \leftarrow dp_{i - 1, j, 0} + \frac{cost \times len_{i - 1, i}}{v}$

$dp_{i, j, 0} \leftarrow dp_{i, j + 1, 1} + \frac{cost \times len_{i, j + 1}}{v}$

$dp_{i, j, 1} \leftarrow dp_{i - 1, j, 0} + \frac{cost \times len_{i - 1, j}}{v}$

$dp_{i, j, 1} \leftarrow dp_{i, j + 1, 1} + \frac{cost \times len_{j, j + 1}}{v}$

# Code

/*
_______                       ________                        _______
/ _____ \                     / ______ \                      / _____ \
/ /     \_\  _     __     _   / /      \ \   _     __     _   / /     \_\
| |          | |   |  |   | | | |        | | | |   |  |   | | | |
| |          | |   |  |   | | | |     __ | | | |   |  |   | | | |
| |       __ \  \  |  |  /  / | |     \ \| | \  \  |  |  /  / | |       __
\ \_____/ /  \  \/ /\ \/  /   \ \_____\  /   \  \/ /\ \/  /   \ \_____/ /
\_______/    \___/  \___/     \______/\__\   \___/  \___/     \_______/
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

#define db double

const int N = 1000;

int n, x;

db dp[N + 50][N + 50][2], sum[N + 50], ans, v;

struct Point {
int pos; db zhi, delta;
} point[N + 50];

bool Cmp(Point a, Point b) {
return a.pos < b.pos;
}

int main() {
while (scanf("%d%lf%d", &n, &v, &x) == 3) {
if (!n && !v && !x) return 0;
for (int i = 1; i <= n; i++)
scanf("%d%lf%lf", &point[i].pos, &point[i].zhi, &point[i].delta);
point[++n].pos = x; point[n].zhi = point[n].delta = 0.0;
sort(point + 1, point + n + 1, Cmp);
int pos;
for (int i = 1; i <= n; i++)
if (point[i].pos == x && point[i].delta == 0.0 && point[i].zhi == 0.0) {
pos = i;
break;
}
ans = 0;
for (int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + point[i].delta,
ans += point[i].zhi;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dp[i][j][0] = dp[i][j][1] = 1e9;
dp[1][n][0] = dp[1][n][1] = 0.0;
for (int l = n - 1; l >= 1; l--)
for (int i = 1; i + l - 1 <= n; i++) {
int j = i + l - 1; db cost = sum[n] - sum[j] + sum[i - 1];
if (i - 1 >= 1) dp[i][j][0] = min(dp[i][j][0], dp[i - 1][j][0] + cost * (db)(point[i].pos - point[i - 1].pos) / v);
if (j + 1 <= n) dp[i][j][0] = min(dp[i][j][0], dp[i][j + 1][1] + cost * (db)(point[j + 1].pos - point[i].pos) / v);
if (j + 1 <= n) dp[i][j][1] = min(dp[i][j][1], dp[i][j + 1][1] + cost * (db)(point[j + 1].pos - point[j].pos) / v);
if (i - 1 >= 1) dp[i][j][1] = min(dp[i][j][1], dp[i - 1][j][0] + cost * (db)(point[j].pos - point[i - 1].pos) / v);
}
printf("%d\n", (int)floor(ans + min(dp[pos][pos][0], dp[pos][pos][1])));
}
return 0;
}

posted @ 2020-11-17 09:03  Tian-Xing  阅读(84)  评论(0编辑  收藏  举报