题目传送门:http://codeforces.com/problemset/problem/28/D

题意:给你$N$个物品,每个物品有其价格$P_i$,之前必须要买的物品价格和$L_i$,之后必须要买的物品价格和$R_i$和价值$W_i$。试给出一种物品的选择方案,使得满足所有选择的物品的条件且选择物品的价值和最大(物品的选择顺序必须要与原来的顺序相同)。$N \leq 10^5 , P , L , R \leq 10^5 , W \leq 10^4$


像背包DP,所以就是背包DP(雾

我们能够发现从物品$i$转移到物品$j$的充要条件是:$R_i=R_j+P_j$且$L_i+P_i=L_j$。将二式相加得$P_i+L_i+R_i=P_j+L_j+R_j$,也就是说$P+L+R$相等的物品才能够互相转移。所以我们可以考虑使用$vector$存每个$P+L+R$对应的物品,对于每个组跑一次DP。因为每一个物品的转移只能从$L$到$L+P$,所以转移是$O(1)$的,所以DP总复杂度为$O(n)$。注意DP数组的清空推荐使用还原而不是memset,这样还原的复杂度才是$O(n)$。

获得了最大的价值之后,对对应的那一个组别再跑一遍DP,跑出方案。方案的记录可以通过记录某一个物品选择前最后选择的物品来实现。总复杂度为$O(n)$。

注意每一个组别一定要有始有终(也就是选择的物品必须要有$L=0$与$R=0$的物品,也可以通过这一个来剪一些枝降低常数)

关于输出方案其实可以使用递归,但是因为本机会爆栈所以用循环+vector输出

 #include<bits/stdc++.h>
 #define MAXN 3000010
 #define MAXM 200010
 using namespace std;

 inline int read(){
     ;
     char c = getchar();
     while(!isdigit(c))
         c = getchar();
     while(isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return a;
 }

 struct thing{
     int w , p , l , r , ind;
 }now;
 vector < thing > v[MAXN];
 vector < int > anss;
  , maxDir;
 bool haveEnd[MAXN];

 void out(int dir){
     ){
         anss.push_back(v[maxDir][dir].ind);
         dir = last[dir];
     }
      ; i >=  ; i--)
         printf("%d " , anss[i]);
 }

 int main(){
     int N = read();
      ; i <= N ; i++){
         now.w = read();
         now.p = read();
         now.l = read();
         now.r = read();
         now.ind = i;
         ){
             cnt[now.p + now.l + now.r]++;
             v[now.p + now.l + now.r].push_back(now);
             )
                 haveEnd[now.p + now.l + now.r] = ;
         }
     }
     memset(maxPri , -0x3f , sizeof(maxPri));
     maxPri[] = ;
      ; i <=  ; i++)
         if(cnt[i] && haveEnd[i]){
              ; j < cnt[i] ; j++)
                 maxPri[v[i][j].l + v[i][j].p] = max(maxPri[v[i][j].l + v[i][j].p] , maxPri[v[i][j].l] + v[i][j].w);
             if(maxN < maxPri[i]){
                 maxN = maxPri[i];
                 maxDir = i;
             }
              ; j < cnt[i] ; j++)
                 maxPri[v[i][j].l + v[i][j].p] = -0x3f3f3f3f;
         }
     memset(last , - , sizeof(last));
     memset(k , - , sizeof(k));
      ; j < cnt[maxDir] ; j++)
         if(maxPri[v[maxDir][j].l + v[maxDir][j].p] < maxPri[v[maxDir][j].l] + v[maxDir][j].w){
             maxPri[v[maxDir][j].l + v[maxDir][j].p] = maxPri[v[maxDir][j].l] + v[maxDir][j].w;
             last[j] = k[v[maxDir][j].l];
             k[v[maxDir][j].l + v[maxDir][j].p] = j;
             ans[v[maxDir][j].l + v[maxDir][j].p] = ans[v[maxDir][j].l] + ;
         }
     printf("%d\n" , ans[maxDir]);
     out(k[maxDir]);
     ;
 }

CF28D Don't fear, DravDe is kind 背包的更多相关文章

  1. CF28D Don't fear, DravDe is kind

    传送门 题意:\(n\)个位置,每个位置有价值\(v_i\)和重量\(p_i\),要选出一些位置,如果要选位置\(i\),那么前面选的重量之和要为\(l_i\),后面选的重量之和要为\(r_i\),求 ...

  2. 【神仙题】【CF28D】 Don't fear, DravDe is kind

    传送门 Description 一个有N辆卡车的车队从城市Z驶向城市3,来到了一条叫做"恐惧隧道"的隧道.在卡车司机中,有传言说怪物DravDe在那条隧道里搜寻司机.有些司机害怕先 ...

  3. CodeForces 28D Don&#39;t fear, DravDe is kind dp

    主题链接:点击打开链接 为了让球队后,删除是合法的.也就是说,对于每一个车辆, l+r+c 一样,按l+r+c分类. 然后dp一下. #include <cstdio> #include ...

  4. [Codeforces 28D] Do not fear,DravDe is kind

    Brief Intro: 对于四元组(v,c,l,r),求其子序列中v最大的和,并使其满足: 1.Ci+Li+Ri相同 2.L1=0,Rn=0 3.Li=Sigma(C1...Ci-1) Soluti ...

  5. codeforces 28D(dp)

    D. Don't fear, DravDe is kind time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  6. 【USACO 3.1】Stamps (完全背包)

    题意:给你n种价值不同的邮票,最大的不超过10000元,一次最多贴k张,求1到多少都能被表示出来?n≤50,k≤200. 题解:dp[i]表示i元最少可以用几张邮票表示,那么对于价值a的邮票,可以推出 ...

  7. HDU 3535 AreYouBusy (混合背包)

    题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...

  8. HDU2159 二维完全背包

    FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. CF2.D 并查集+背包

    D. Arpa's weak amphitheater and Mehrdad's valuable Hoses time limit per test 1 second memory limit p ...

随机推荐

  1. 我的Java之旅 第七课 JAVA WEB 会话管理

    1.隐藏域       隐藏域其实不是Servlet/JSP的会话管理机制的内容,但它能实现简单的页面状态记录的效果. 2.Cookie    Cookie类    setMaxAge() 设置有效期 ...

  2. Linux 学习笔记之超详细基础linux命令 Part 13

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 12---------------- ...

  3. Java并发编程(十四)Java内存模型

    1.共享内存和消息传递 线程之间的通信机制有两种:共享内存和消息传递:在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.在消息传递的并发模型里,线程 ...

  4. Spark程序数据结构优化

    场景: 1.scala中的对象:对象头是16个字节(包含指向对象的指针等源数据信息),如果对象中只有一个int的属性,则会占用20个字节,也就是说对象的源数据占用了大部分的空间,所以在封装数据的时候尽 ...

  5. 洗礼灵魂,修炼python(37)--面向对象编程(7)—了解魔法方法

    也许上一篇博文提到的property内置函数的用法你还觉得记忆犹新,那么有没有更多的类似的方法呢?有的,就是本篇文章要说的魔法方法 魔法方法 1.什么是魔法方法 (其实前面已经提到多次,每次我都是说暂 ...

  6. jquery常用表单操作

    //js将表单序列化成对象 $.fn.serializeObject = function () { var $els = $(this).find("[name]"); var ...

  7. Linux文件和目录的粘滞位(sticky bit)

    今天维护系统时发现一个非常诡异的问题:AAA用户和BBB用户同属AAA组,但用AAA用户创建的文件,权限设置为777后,还是不能用BBB用户删除.诡异! 几经周转,发现AAA用户创建文件位置的上层目录 ...

  8. CentOS7查询系统版本内核信息

    1. 查看版本号 查看CentOS的版本号命令: [root@localhost ~]# cat /etc/centos-releaseCentOS Linux release 7.4.1708 (C ...

  9. C#生成真值表

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. logstash启动失败的问题追查

    在实验中logstash是作为日志过滤器的作用,日志收集使用的则是filebeat组件.redis作为缓存器,logstash从redis中拉取数据进行过滤并传给elasticsearch组件. 但是 ...