UVA1336修缮长城

The Great Wall of China is truly one of the greatest wonders of the world. In 3-rd century BC, Emperor Qin Shi Huang connected the defensive structures built earlier by the states of Qin, Yan, and Zhao kingdoms. The purpose of the wall was to defend against raids by the barbarians from Mongolia and Manchuria. The wall was extended and renovated in later centuries, creating an impressive 6,700 km long fortification.

The centuries have left their mark on the wall, there are several sections that need immediate renovation. These sections have to be repaired as soon as possible since they deteriorate every day: if we do not fix them now, it will be more expensive to repair them later. Thus the Ministry of Monuments have designed and built the world’s first Great Wall Automatic Repair Robot (GWARR), to repair the damaged sections (we are in the 21-st century, aren’t we?) Your task is to write the software that will guide the robot and decide the order in which the sections are to be repaired.

For the purpose of this problem, we assume that the Great Wall is a long straight line, and every location on the wall is identified by a single number (say, the distance from one end). The GWARR is placed at some location on the wall and it can move with constant speed in both directions. For each damaged section you are given its location, how much it would cost to repair now, and how the cost would increase if repaired later. The GWARR works so efficiently that once it is at the exact location of the damaged section it can repair the wall immediately.

Input

The input contains several blocks of test cases. Each case begins with a line containing three integers: an integer 1n1000, the number of damaged sections, an integer 1v100, the speed of the GWARR in distance units/time units, and an integer 1x500000, the initial position of the GWARR. The next n lines describe the n damaged sections that have to be repaired. Each line contains three integers: the location 1x500000 of the section, the cost 0c50000 of repairing it immediately, and 150000, the increase in cost per time unit. Therefore, if the section is repaired after t time units have passed, then we have to pay c + t units of money. It can be assumed that the locations of the sections are all different, and the initial location of the robot is not on the list of damaged seetions.

The input is terminated by a test case with n = v = x = 0.

Output

For each test case, you have to output a line containing a single number, the minimum cost of repairing the wall. This number should be an integer, round down the result, if necessary. It can be assumed that the minimum cost is not more than 1000000000.

In the optimum solution for the first test case below, we first fix loeation 998 at the cost of 600, then the location 1010 at the cost of l400, and finally we fix the location 996 at the cost of 84, giving the total cost 2084.

Sample Input

3 1 1000
1010 0 100
998 0 300
996 0 3
3 1 1000
1010 0 100
998 0 3
996 0 3
0 0 0
Sample Output

2084
1138

我有话说:
在我们把所有的点的位置排序后会发现已修好的点是一个区间,因为我们在修好点的时候总是想着在走路的时候顺带修好。
所以只要枚举[i,j]的i-1,j+1位置就好了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cassert>
using namespace std;

const int maxn = 1000 + 5;
const double INF = 1e30;

struct Section {
  double x, c, dt;
  bool operator < (const Section& rhs) const {
    return x < rhs.x;
  }
} s[maxn];

int kase, n;
int vis[maxn][maxn][2];
double v, x, d[maxn][maxn][2];
double psdt[maxn]; // prefix sum of dt

//[i,j]区间内是已经修好的长城
double cost(double x1, double x2, int i, int j) {
  double finished_dt = 0;
  assert(i <= j);
  if(i >= 0 && j >= 0) finished_dt += psdt[j] - psdt[i-1];
  return (psdt[n] - finished_dt) * fabs(x2 - x1) / v;
}

double dp(int i, int j, int p) {//p=0表示在i位置,p=1表示在j位置
  if(i == 1 && j == n) return 0;
  double& ans = d[i][j][p];
  if(vis[i][j][p] == kase) return ans;
  vis[i][j][p] = kase;

  ans = INF;
  double x = (p == 0 ? s[i].x : s[j].x);
  if(i > 1) ans = min(ans, dp(i-1, j, 0) + cost(x, s[i-1].x, i, j));
  if(j < n) ans = min(ans, dp(i, j+1, 1) + cost(x, s[j+1].x, i, j));
  return ans;
}

int main() {
  memset(vis, 0, sizeof(vis));
  while(scanf("%d%lf%lf", &n, &v, &x) == 3 && n) {
    ++kase;
    double sumc = 0;
    for(int i = 1; i <= n; i++) {
      scanf("%lf%lf%lf", &s[i].x, &s[i].c, &s[i].dt);
      sumc += s[i].c;
    }
    sort(s+1, s+n+1); //排序按照位置x升序排列

    psdt[0] = 0;
    for(int i = 1; i <= n; i++)
      psdt[i] = psdt[i-1] + s[i].dt;//累加各个点单位时间所增加的费用

    s[0].x = -INF;
    s[n+1].x = INF;//防止越界
    double ans = INF;
    for(int i = 1; i <= n+1; i++)
      if(x > s[i-1].x && x < s[i].x) {//机器人初始位置查找
          //ans记因为时间花费所产生的花费
        if(i > 1) ans = min(ans, dp(i-1, i-1, 0) + cost(x, s[i-1].x, -1, -1)); //左
        if(i <= n) ans = min(ans, dp(i, i, 0) + cost(x, s[i].x, -1, -1)); //右
        break;
      }
    printf("%.0lf\n", floor(ans + sumc));
  }
  return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值