[小明打联盟][斜率/单调队列 优化dp][背包]
链接:https://ac.nowcoder.com/acm/problem/14553
来源:牛客网
题目描述
小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时间和固定的伤害值为:
1.乌鸦坐飞机 释放时间:x 固定伤害值:a
2.蜘蛛吃耳屎 释放时间:y 固定伤害值:b
3.饿狼前进 释放时间:z 固定伤害值:c
他还有一个大招,其释放的时间是一个区间【L,R】,可以在区间内任意时间点释放出技能,其如果在L+i时刻释放技能,其能够打出的伤害值为:temp+A*i
这里temp值表示技能的基础伤害(同时也就是在时刻L释放技能的伤害值),A是一个常数。
小明很喜欢研究连招使得在有限的时间内打出最高的伤害,现在他想要在T长度单位时间内打出最高的伤害,问这个最大伤害值。
输入描述:
本题包含多组数据。
输入格式为:
T
x a
y b
z c
L R temp A
数据范围:
1<=T<=1e5
1<=x,y,z,L,R<=T
L<=R
<=a,b,c,temp,A<=1e5
输出描述:
输出包含一行,输出能够打出的最高伤害值。
8
3 1
2 3
1 3
3 3 3 3
输出
24
备注:
大招:蓄力时间最短L秒,最多R秒。无限次释放,释放之后照成的伤害是随着时间增加的
蓄力L秒释放能够造成Temp的伤害
蓄力L+1秒释放能够造成Temp+1*A的伤害
依次类推
题意:小明有三个小技能和一个大招,每个小技能消耗ai的时间,打出bi的伤害,大招的基础伤害为temp,基础时间为L,大招可以蓄力,得到的伤害为temp+(T-L)*A,其中T为大招的时间,上限为R,求总时间为t打出的最高伤害
题解:对于三个小技能可以直接使用普通的背包dp,而对于大招,如果暴力地把大招时间拆成L,L+1....R,那么复杂度将是O(N^2),很明显会超时,而观察到对大招来说dp[i]=max(dp[j]+temp+A*(i-L-j)),所以对于j>k, 如果 j 相对于k更优,那么(dp[j]+temp+A*(i-L-j)) - (dp[k]+temp+A*(i-L-k)) > 0,所以有dp[j]-dp[k]>A*(j-k),可以使用斜率优化dp,而由于这里的A为常数,和 i 无关,所以可以直接知道当前点是否最优,不需要维护凸包,也就是可以不使用斜率优化dp,而使用单调队列优化dp(斜率优化dp和单调队列优化dp区别就在插入新点时前者是维护凸包后者是维护单调队列)
斜率优化dp
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
using namespace std;
//#define io_test
#define debug(x) cout<<x<<"####"<<dp[x][0]<<"##"<<dp[x][1]<<endl;
typedef long long ll;
ll dp[],pq[];
int main()
{
#ifdef io_test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // io_test
//int n,m;
int t;
while(scanf("%d",&t)==){
ll x,y,z,a,b,c;
//queue<struct pot>pq;
scanf("%lld%lld%lld%lld%lld%lld",&x,&a,&y,&b,&z,&c);
ll l,r,temp,A;
scanf("%lld%lld%lld%lld",&l,&r,&temp,&A);
int head=;
int tail=;
for(int i=;i<=t;i++){
dp[i]=dp[i-];
if(i>=x){
dp[i]=max(dp[i],dp[i-x]+a);
}
if(i>=y){
dp[i]=max(dp[i],dp[i-y]+b);
}
if(i>=z){
dp[i]=max(dp[i],dp[i-z]+c);
}
if(i>=l){
while((head+<=tail&&(i-pq[head]>r||(dp[pq[head+]]-dp[pq[head]]>(pq[head+]-pq[head])*A))))head++;
if(head<=tail){
dp[i]=max(dp[i],dp[pq[head]]+temp+A*(i-pq[head]-l));
}
while(tail-head>=&&(dp[i-l+]-dp[pq[tail]])*(pq[tail]-pq[tail-])>(i-l+-pq[tail])*(dp[pq[tail]]-dp[pq[tail-]]))tail--;//维护凸包
++tail;
pq[tail]=i-l+;
}
}
printf("%lld\n",dp[t]);
}
return ;
}
单调队列优化dp
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
using namespace std;
//#define io_test
#define debug(x) cout<<x<<"####"<<dp[x][0]<<"##"<<dp[x][1]<<endl;
typedef long long ll;
ll dp[],pq[];
int main()
{
#ifdef io_test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // io_test
//int n,m;
int t;
while(scanf("%d",&t)==){
ll x,y,z,a,b,c;
//queue<struct pot>pq;
scanf("%lld%lld%lld%lld%lld%lld",&x,&a,&y,&b,&z,&c);
ll l,r,temp,A;
scanf("%lld%lld%lld%lld",&l,&r,&temp,&A);
int head=;
int tail=;
for(int i=;i<=t;i++){
dp[i]=dp[i-];
if(i>=x){
dp[i]=max(dp[i],dp[i-x]+a);
}
if(i>=y){
dp[i]=max(dp[i],dp[i-y]+b);
}
if(i>=z){
dp[i]=max(dp[i],dp[i-z]+c);
}
if(i>=l){
while((head+<=tail&&(i-pq[head]>r||(dp[pq[head+]]-dp[pq[head]]>(pq[head+]-pq[head])*A))))head++;
if(head<=tail){
dp[i]=max(dp[i],dp[pq[head]]+temp+A*(i-pq[head]-l));
}
while(tail>=head&&(dp[i-l+]-dp[pq[tail]])>A*(dp[i-l+]-dp[pq[tail]]))tail--;//维护单调队列
++tail;
pq[tail]=i-l+;
}
}
printf("%lld\n",dp[t]);
}
return ;
}
这题还有一个背包的写法,因为大招的伤害和时间的关系是条直线,所以最后的结果一定是若干小技能+若干次不蓄力大招+若干次蓄满力大招+一次不满的大招(注意只会使用一次不满的大招,这点决定了可以直接背包而不会T掉),也就是说真正需要暴力枚举的大招时间只有一次,也就是那次没有满的大招,所以复杂度就是O(N)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
using namespace std;
//#define io_test
#define debug(x) cout<<x<<"####"<<dp[x][0]<<"##"<<dp[x][1]<<endl;
typedef long long ll;
ll dp[],pq[];
int main()
{
#ifdef io_test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // io_test
//int n,m;
int t;
while(scanf("%d",&t)==){
ll x,y,z,a,b,c;
//queue<struct pot>pq;
scanf("%lld%lld%lld%lld%lld%lld",&x,&a,&y,&b,&z,&c);
ll l,r,temp,A;
scanf("%lld%lld%lld%lld",&l,&r,&temp,&A);
int head=;
int tail=;
for(int i=;i<=t;i++){
dp[i]=dp[i-];
if(i>=x){
dp[i]=max(dp[i],dp[i-x]+a);
}
if(i>=y){
dp[i]=max(dp[i],dp[i-y]+b);
}
if(i>=z){
dp[i]=max(dp[i],dp[i-z]+c);
}
if(i>=l){
dp[i]=max(dp[i],dp[i-l]+temp);
}
if(i>=r){
dp[i]=max(dp[i],dp[i-r]+temp+A*(r-l));
}
}
for(int i=l;i<=r;i++){//未满的大招只有一次,所以只进行一次枚举更新
if(t>=i)dp[t]=max(dp[t],dp[t-i]+temp+A*(i-l));
}
printf("%lld\n",dp[t]);
}
return ;
}
[小明打联盟][斜率/单调队列 优化dp][背包]的更多相关文章
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 算法笔记--单调队列优化dp
单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...
- 【bzoj3831】[Poi2014]Little Bird 单调队列优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6826475.html 题目描述 In the Byteotian Line Forest there are t ...
- 动态规划专题(四)——单调队列优化DP
前言 单调队列优化\(DP\)应该还算是比较简单容易理解的吧,像它的升级版斜率优化\(DP\)就显得复杂了许多. 基本式子 单调队列优化\(DP\)的一般式子其实也非常简单: \[f_i=max_{j ...
- 单调队列优化DP || [NOI2005]瑰丽华尔兹 || BZOJ 1499 || Luogu P2254
题外话:题目极好,做题体验极差 题面:[NOI2005]瑰丽华尔兹 题解: F[t][i][j]表示第t时刻钢琴位于(i,j)时的最大路程F[t][i][j]=max(F[t-1][i][j],F[t ...
- 【笔记篇】单调队列优化dp学习笔记&&luogu2569_bzoj1855股票交♂易
DP颂 DP之神 圣洁美丽 算法光芒照大地 我们怀着 崇高敬意 跪倒在DP神殿里 你的复杂 能让蒟蒻 试图入门却放弃 在你光辉 照耀下面 AC真心不容易 dp大概是最经久不衰 亘古不化的算法了吧. 而 ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- bzoj1855: [Scoi2010]股票交易--单调队列优化DP
单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...
随机推荐
- PHP用post来进行Soap请求
最近调了一个Soap请求C# webservice的项目.网上坑不少. 使用原生的SoapClient库请求也是失败.只好用post来进行模拟了.代码贴出来,给大家参考一下. <?php nam ...
- C语言文件(例题及要点)
char str[100] = "HELLOhello 123456789ABCD abcd!"; FILE *fp1, &fp2;//文件指针 fp1 = fopen(& ...
- 小飞侠带你精通Python网络编程系列03-Python版本的选择
1. 目前Python有两个主要版本Python2.X和Python3.X 2. Python2.X最后一个版本是2.7,目前(2018年10月21日)Python3.X最新版本为3.7 3. 很不幸 ...
- Scientific Toolworks Understand 软件教程
系统:Ubuntu16.04 x64 安装 安装包 下载地址: part1:http://download.csdn.net/detail/p942005405/9711128 part2:http: ...
- Problem 8: Largest product in a series
先粘实现代码,以后需要再慢慢补充思路 s = ''' 73167176531330624919225119674426574742355349194934 9698352031277450632623 ...
- 20175223 实验一 《JAVA开发环境的熟悉》实验报告
目录 北京电子科技学院(BESTI)实验报告 实验名称:实验一 Java开发环境的熟悉 实验内容.步骤与体会: 一.实验一 Java开发环境的熟悉-1 二.实验一 Java开发环境的熟悉-2 步骤: ...
- Python04(基础语法)
Trainning-day03回顾1.输出重定向 > 将输出到终端的内容输出到指定文件 命令 > 文件 注意: 1.如果文件存在,覆盖原文件 2.如果文件不存在,直接创建新文件2.输出追加 ...
- 马凯军201771010116《面向对象与程序设计Java》第十六周知识学习总结
一:理论知识部分 1.线程的概念: 程序是一段静态的代码,它是应用程序执行的蓝 本. ‐进程是程序的一次动态执行,它对应了从代码加 载.执行至执行完毕的一个完整过程. 多线程是进程执行过程中产生的多条 ...
- Sublime Text 3 安装 Package Control
1.打开sublime text 3 2.Ctrl+`打开控制台或者View->Show Console菜单打开命令行,输入下面这段代码后按Enter键 import urllib.reques ...
- 使用lua读文件并输出到stdin
io.input("c:\\AudioCom.log") t= io.read("*all") io.write(t) 三行代码搞定,简洁的不像话 io.rea ...