zoukankan      html  css  js  c++  java
  • 洛谷P2466 [SDOI2008]Sue的小球 题解 区间DP+费用提前计算

    题目链接:https://www.luogu.com.cn/problem/P2466

    题目大意:略。

    解题思路:

    首先将 (n) 个彩蛋按照 (x) 从小到大排序。

    然后定义状态 (f[L][R][s]),其含义为:

    • (s=0) 时:接完了第 ([L,R]) 范围内的所有彩蛋,且当前处在最左边的位置((L)处),收获的得分+给未来造成的得分的损耗之和的最大值;
    • (s=1) 时:接完了第 ([L,R]) 范围内的所有彩蛋,且当前处在最右边的位置((R)处),收获的得分+给未来造成的得分的损耗之和的最大值。

    则状态转移方程为:

    (L = R) 时,

    [f[L][R][s] = y_L - |x_0 - x_L| imes sum_{1 le i le n} v_i ]

    (L lt R) 时,

    [f[L][R][0] = max{f[L+1][R][0] + y_L - (sum_{ile L} v_i + sum_{i gt R} v_i) imes (x_{L+1} - x_L), f[L+1][R][1] + y_L - (sum_{ile L} v_i + sum_{i gt R} v_i) imes (x_R - x_L) } ]

    [f[L][R][1] = max {f[L][R-1][0] + y_R - (sum_{i lt L} v_i + sum_{i ge R} v_i) imes (x_R - x_L) , f[L][R-1][1] + y_R - (sum_{i lt L} v_i + sum_{i ge R} v_i) imes (x_R - x_{R-1}) } ]

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1010;
    struct Node {
        int x, y, v;
        Node() {};
        Node(int _x, int _y, int _v) { x = _x; y = _y; v = _v; }
    } a[maxn];
    bool cmp(Node a, Node b) {
        return a.x < b.x;
    }
    int n, x0;
    long long f[maxn][maxn][2], sumv[maxn];
    bool vis[maxn][maxn][2];
    long long dfs(int L, int R, int s) {
        if (L == R) {
            return a[L].y - abs(x0 - a[L].x) * sumv[n];
        }
        if (vis[L][R][s]) return f[L][R][s];
        vis[L][R][s] = true;
        if (s == 0) {
            long long tmp1 = dfs(L+1, R, 0) + a[L].y - (sumv[L] + sumv[n] - sumv[R]) * (a[L+1].x - a[L].x);
            long long tmp2 = dfs(L+1, R, 1) + a[L].y - (sumv[L] + sumv[n] - sumv[R]) * (a[R].x - a[L].x);
            return f[L][R][0] = max(tmp1, tmp2);
        }
        else {  // s == 1
            long long tmp1 = dfs(L, R-1, 0) + a[R].y - (sumv[L-1] + sumv[n] - sumv[R-1]) * (a[R].x - a[L].x);
            long long tmp2 = dfs(L, R-1, 1) + a[R].y - (sumv[L-1] + sumv[n] - sumv[R-1]) * (a[R].x - a[R-1].x);
            return f[L][R][1] = max(tmp1, tmp2);
        }
    }
    int main() {
        scanf("%d%d", &n, &x0);
        for (int i = 1; i <= n; i ++) scanf("%d", &a[i].x);
        for (int i = 1; i <= n; i ++) scanf("%d", &a[i].y);
        for (int i = 1; i <= n; i ++) scanf("%d", &a[i].v);
        sort(a+1, a+1+n, cmp);
        for (int i = 1; i <= n; i ++) sumv[i] = sumv[i-1] + a[i].v;
        printf("%.3lf
    ", (double) max(dfs(1, n, 0), dfs(1, n, 1))/ 1000.0);
        return 0;
    }
    
  • 相关阅读:
    iphone 拨打电话的 两种方法-备
    vi编辑器经典技巧 -备
    iOS图片压缩问题
    NSStirng、NSArray、以及枚举(Method小集合)
    宏定义 button 方法 --备
    debug 输出 以及宏定义--备
    从别人写的 Object-C 中 Singleton (单例) 模式 中的一些理解--备
    makefile编写---.c .cpp 混合编译makefile 模板
    图像处理之基础---线性卷积和循环卷积的区别
    图像处理之基础---卷积去噪
  • 原文地址:https://www.cnblogs.com/quanjun/p/13603864.html
Copyright © 2011-2022 走看看