CF28D Don't fear, DravDe is kind 背包
题目传送门: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 背包的更多相关文章
- CF28D Don't fear, DravDe is kind
传送门 题意:\(n\)个位置,每个位置有价值\(v_i\)和重量\(p_i\),要选出一些位置,如果要选位置\(i\),那么前面选的重量之和要为\(l_i\),后面选的重量之和要为\(r_i\),求 ...
- 【神仙题】【CF28D】 Don't fear, DravDe is kind
传送门 Description 一个有N辆卡车的车队从城市Z驶向城市3,来到了一条叫做"恐惧隧道"的隧道.在卡车司机中,有传言说怪物DravDe在那条隧道里搜寻司机.有些司机害怕先 ...
- CodeForces 28D Don't fear, DravDe is kind dp
主题链接:点击打开链接 为了让球队后,删除是合法的.也就是说,对于每一个车辆, l+r+c 一样,按l+r+c分类. 然后dp一下. #include <cstdio> #include ...
- [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 ...
- codeforces 28D(dp)
D. Don't fear, DravDe is kind time limit per test 2 seconds memory limit per test 256 megabytes inpu ...
- 【USACO 3.1】Stamps (完全背包)
题意:给你n种价值不同的邮票,最大的不超过10000元,一次最多贴k张,求1到多少都能被表示出来?n≤50,k≤200. 题解:dp[i]表示i元最少可以用几张邮票表示,那么对于价值a的邮票,可以推出 ...
- HDU 3535 AreYouBusy (混合背包)
题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...
- HDU2159 二维完全背包
FATE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- CF2.D 并查集+背包
D. Arpa's weak amphitheater and Mehrdad's valuable Hoses time limit per test 1 second memory limit p ...
随机推荐
- 我的Java之旅 第七课 JAVA WEB 会话管理
1.隐藏域 隐藏域其实不是Servlet/JSP的会话管理机制的内容,但它能实现简单的页面状态记录的效果. 2.Cookie Cookie类 setMaxAge() 设置有效期 ...
- Linux 学习笔记之超详细基础linux命令 Part 13
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 12---------------- ...
- Java并发编程(十四)Java内存模型
1.共享内存和消息传递 线程之间的通信机制有两种:共享内存和消息传递:在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.在消息传递的并发模型里,线程 ...
- Spark程序数据结构优化
场景: 1.scala中的对象:对象头是16个字节(包含指向对象的指针等源数据信息),如果对象中只有一个int的属性,则会占用20个字节,也就是说对象的源数据占用了大部分的空间,所以在封装数据的时候尽 ...
- 洗礼灵魂,修炼python(37)--面向对象编程(7)—了解魔法方法
也许上一篇博文提到的property内置函数的用法你还觉得记忆犹新,那么有没有更多的类似的方法呢?有的,就是本篇文章要说的魔法方法 魔法方法 1.什么是魔法方法 (其实前面已经提到多次,每次我都是说暂 ...
- jquery常用表单操作
//js将表单序列化成对象 $.fn.serializeObject = function () { var $els = $(this).find("[name]"); var ...
- Linux文件和目录的粘滞位(sticky bit)
今天维护系统时发现一个非常诡异的问题:AAA用户和BBB用户同属AAA组,但用AAA用户创建的文件,权限设置为777后,还是不能用BBB用户删除.诡异! 几经周转,发现AAA用户创建文件位置的上层目录 ...
- CentOS7查询系统版本内核信息
1. 查看版本号 查看CentOS的版本号命令: [root@localhost ~]# cat /etc/centos-releaseCentOS Linux release 7.4.1708 (C ...
- C#生成真值表
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- logstash启动失败的问题追查
在实验中logstash是作为日志过滤器的作用,日志收集使用的则是filebeat组件.redis作为缓存器,logstash从redis中拉取数据进行过滤并传给elasticsearch组件. 但是 ...