嘘~ 正在从服务器偷取页面 . . .

CF480D Parcels 题解


CF480D Parcels 题解

题目链接:CF480D Parcels

题意

\(n\) 件包裹,每个包裹是一个盒子,都有它自身的质量和载重 (即它上方能承受的最大质量)。cxy 最近得到了一个新的包裹处理系统,这个系统以如下方式工作。初始时,有一个(可以堆放盒子的)平台,它的载重为 \(S\),接下来,你能以如下的规则在平台上堆放盒子:

  1. 如果平台是空的,你可以将盒子堆放在平台上,否则,你只能在新的盒子放在最高的盒子上面。
  2. 任何时刻,(平台上)所有盒子的总质量不能超过 \(S\) (即平台的载重)。
  3. 对任意一个盒子,任何时刻,在它上面的所有盒子的总质量不能超过这个盒子的载重。
  4. 并且你只能取走当前位于最上面的盒子(即形成栈型结构)。

系统接收到了这 \(n\) 件包裹,已知第 \(i\) 个包裹在时刻 \(\text{in}_i\) 出现,它的质量和载重分别为 \(w_i,s_i\),每个包裹都有它的价值,其中第 \(i\) 个包裹的价值为 \(v_i\)。然而,为了获得(赚得)这 \(v_i\) 的价值,这个系统要求它刚好在时刻 \(\text{out}_i\) 被出售,否则将无法获得任何价值。于是,cxy 可以选择跳过部分包裹(即不接收这些包裹),当然她也无法获得任何价值。

任何操作所花费的时间可以忽略不计,这意味着你可以在一个时刻做多件事情(比如取走若干包裹,在堆放若干包裹)。

注意一旦一个包裹被取走后,它就不会影响后续对包裹的操作。

由于这系统非常复杂,并且包裹数有很多,cxy 想要知道如果她合理利用这个系统,她最多能得到多少钱。

输入格式

第一行包含两个非负整数 \(n,S(n≤500,S≤1000)\) ,表示包裹的个数和平台的载重。

接下来的 \(n\) 行,每行包含 \(5\) 个非负整数 \(\text{in}_i,\text{out}_i,w_i,s_i,v_i(0\le\text{in}_i<\text{out}_i<2n,~0 \le w_i,s_i\le 1000,~1\le v_i\le 10^6)\)

保证不存在两个包裹的出现时间 (\(\text{in}_i\)) 和出售时间 (\(\text{out}_i\)) 均相同。

输出格式

输出一行一个整数,表示 cxy 能得到的价值的最大值。

容易发现,时间有交集的两个包裹,如果他们不是包含关系,则一定只能二选一。

但如果是包含关系,这俩就都可以选。并且在一个大集合内,可以选若干个小的。

再加上这个栈的性质,很容易把它和树联系到一起。

我们把每个包裹按右端点排序,则若 \(v\)\(u\) 的子节点,\(v\) 一定出现的比 \(u\) 早,这就方便dp了。

\(f_{i,j}\) 表示对于第 \(i\) 个包裹(节点),当前剩余的最大载重量为 \(j\)\(i\) 所在子树中的最大价值。

注意,由于原图可能是个森林,所以我们要加个虚拟节点(平台)把它们连起来。

考虑转移。设 \(g_b (\text{in}_i \le b \le \text{out}_i)\) 表示到时刻 \(b\) 位置的最大价值,则对于 \(i\) 的某个子节点 \(u\) ,当 \(b = \text{out}_u\)\[ \large g_b \uparrow g_{\text{in}_u} + f_{u,\min \left\{j-w_i, s_i\right\}} \] 最后别忘了它自己, \(f_{i,j}=g_{\text{out}_i} + v_i\) 。最终答案就是虚拟点载重为 \(S\) 的答案。

时间复杂度 \(\mathcal{O}(n^3)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(555))
#define M ((int)(1e3 + 15))

struct node
{
    int i,o,w,s,v;
    void read() { cin >> i >> o >> w >> s >> v; }
    friend bool operator < (node a, node b) {
        return a.o == b.o ? (a.i > b.i) : (a.o < b.o);
    }
}p[N];
int n,S,f[N][M],g[M];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n >> S; p[0] = {0, (n << 1 | 1), 0, S, 0};
    for(int i = 1; i <= n; i++) { p[i].read(); } sort(p, p + 1 + n);
    for(int i = 0; i <= n; i++)
        for(int j = p[i].w; j <= S; j++)
        {
            int b = p[i].i, nj = min(j - p[i].w, p[i].s); g[b] = 0;
            for(int k = 0; k < i; k++)
                if(p[i].i <= p[k].i)
                {
                    for(; b < p[k].o; b++) g[b + 1] = g[b];
                    up(g[b], g[p[k].i] + f[k][nj]);
                }
            f[i][j] = g[b] + p[i].v;
        }
    cout << f[n][S] << '\n';
    return 0;
}

参考文献

[1] https://yhx-12243.github.io/OI-transit/records/cf480D.html


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录