zoukankan      html  css  js  c++  java
  • UVA1336 修缮长城 Fixing the Great Wall

    Description

    传送门


    Solution

    因为只要经过就会修所以最优的修缮策略是从起点开始往左或往右修一段区间,所以考虑反向区间(dp)

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

    那么转移时不需要考虑区间([i, j]),只需要考虑除了区间([i, j])以外的点。

    发现修缮区间([i, j])时花费的时间会对以后要修复的点产生影响,具体的,还没有修复的那些点对答案的贡献会加上从区间([i, j])转移到下个区间的时间乘单位时间的代价。

    所以只需计算区间和区间转移时花费的时间。

    注意到修缮完一个区间后一定是在区间的左/右端点,所以可以设(dp_{i, j, 0/1})表示当前修缮到区间([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 imes len_{i - 1, i}}{v} ]

    [dp_{i, j, 0} leftarrow dp_{i, j + 1, 1} + frac{cost imes len_{i, j + 1}}{v} ]

    [dp_{i, j, 1} leftarrow dp_{i - 1, j, 0} + frac{cost imes len_{i - 1, j}}{v} ]

    [dp_{i, j, 1} leftarrow dp_{i, j + 1, 1} + frac{cost imes 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
    ", (int)floor(ans + min(dp[pos][pos][0], dp[pos][pos][1])));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android PopupWindow显示位置和显示大小
    线性回归与梯度下降
    nginx启动过程分析
    项目管理学习笔记之三.绩效分析
    会计总论读书笔记
    电子书阅读及工具
    mybatis-mysql小优化
    List去重
    JAVA8之lambda表达式详解,及stream中的lambda使用
    linux部署mongodb及基本操作
  • 原文地址:https://www.cnblogs.com/Tian-Xing-Sakura/p/13992424.html
Copyright © 2011-2022 走看看