P5858 「SWTR-3」Golden Sword

第一道自己想出递推公式并且成功\(AC\)的\(dp\)绿题。

题意简述

有\(n\)种原料,每个原料有一个耐久度\(a[i]\),必须按照\(1,2,…,n\)的顺序放入炼金锅。但是炼金锅的容量是有限的,只能放\(w\)个原料,所以在每次放入原料之前,都可以选择取出\(0\sim s\)个原料再放当前的原料。

放入第\(i\)个原料后,所锻造的武器的总耐久度就会增加\(len*a[i]\)(\(len\)表示当前炼金锅中原料个数)。

询问最大的“武器总耐久度”。

数据范围:

输入输出格式

输入:\(n,w,s\),而后\(n\)个整数\(a_1,a_2,…,a_n\)。

输出:一行,表示最终答案。

思路简述

用下面的样例进行演示:

7 4 2
-5 3 -1 -4 7 -6 5

输出:17

如图,用\(f\)作为\(dp\)数组。\(f[i][j]\)表示放了前\(i\)个,放完后锅中还有\(j\)个的最大值。

递推公式:\(f[i][j]=a[i]*j+max(f[i-1][k])(j-1\leq k\leq min(w,j+s-1))\)

例如下图求\(f[6][2]\),就是用\(max(绿色部分)+2倍的紫色部分\)。

怎么推导呢?我们发现\(dp[6][2]\)肯定可以由\(dp[5][1]\)推来的,因为\(f[5][1]\)的基础上,不拿走任何元素就直接放入第\(6\)个元素,状态就是\(f[6][2]\)。

那么\(dp[6][2]\)还能由哪些状态推来呢?别忘了每放一个原料前,我们可以拿出最多\(s=2\)个元素。所以\(f[6][2]\)自然也能通过\(f[5][2]\)(拿\(1\)个元素)、\(f[5][3]\)(拿\(2\)个元素)。

这样我们可以写出代码(见Code部分#1)。

优化

然而这份代码提交上去,面对数据更大的点会\(TLE\)。这是因为我们每求一次最大值都要遍历上一行。怎么解决这个问题呢?没错,这就是「单调队列优化\(dp\)」

单调队列我先开个坑,到时候填。

使用\(maxx[j]\)表示当前行即\(f[i]\)中,以\(j\)结尾,往前长度为\(min(j,s+1)\)的最大值。每次求完这一行的\(f\),就处理出\(maxx\)数组供下一行使用。

这样求\(f[i][j]\)时,就用\(maxx[j+s-1]\)就好了。

此时我们发现\(f\)也可以优化空间为一维(与HDU1024 Max Sum Plus Plus有异曲同工之妙,无论是在推导过程还是优化方面),这样既优化了时间,还优化了空间,一举两得。

注意递推完,下一行最多用到\(max(i+s,w+s)\),所以维护\(maxx\)时只需要循环至\(max(i+s,w+s)\)即可。

时间复杂度\(O(nw)\),代码见#2。

Code

#1
#include<bits/stdc++.h>
#define int long long
using namespace std;
int s,w,n,a[5010];
int f[5010][5010];
signed main(){
cin>>n>>w>>s;
for(int i=1;i<=n;i++) cin>>a[i];
memset(f,0x80,sizeof f);//long long极小值
for(int i=0;i<=w;i++) f[0][i]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=w;j++){
if(j>i) break;
for(int k=j-1;k<j+s;k++){
if(k>w) break;
f[i][j]=max(f[i][j],f[i-1][k]);
}
f[i][j]+=a[i]*j;
cout<<f[i][j]<<" ";
}
cout<<endl;
}
int ans=LLONG_MIN;
for(int i=1;i<=w;i++) ans=max(ans,f[n][i]);
cout<<ans;
return 0;
}
#2
#include<bits/stdc++.h>
#define int long long
using namespace std;
int s,w,n,a[5010],maxx[5010];
int f[5010];
deque<int> q;
signed main(){
cin>>n>>w>>s;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=w;j++){
if(j>i) break;
f[j]=maxx[j+s-1]+a[i]*j;
}
q.clear();
for(int j=1;j<=w+s;j++){
if(j>i+s) break;
if(j<=i&&j<=w){//如果i个元素加完了,就只出不入
while(!q.empty()&&f[j]>=f[q.front()]) q.pop_back();
q.push_back(j);
}
if(q.front()+s+1<=j) q.pop_front();
maxx[j]=f[q.front()];
}
}
int ans=LLONG_MIN;
for(int i=1;i<=w;i++) ans=max(ans,f[i]);
cout<<ans;
return 0;
}

[题解]P5858 Golden Sword的更多相关文章

  1. P5858 「SWTR-03」Golden Sword

    题面: Link 题面有点长,不想粘了,QAQ. 题解: 一句话题意,你有 \(n\) 件物品需要依次放进去,每个物品放进去之后会得到一定的权值,为当前锅炉里面的物品的数量乘以 \(a_i\) 每次在 ...

  2. P5858 Golden Swold

    写在前面 简单的单调队列优化 DP 处理略微有点恶心,于是乎,用来取 \(\max\) 的极小值直接开到了 long long 的最小极限,了 define int long long /cy 算法思 ...

  3. dp优化 | 各种dp优化方式例题精选

    前言 本文选题都较为基础,仅用于展示优化方式,如果是要找题单而不是看基础概念,请忽略本文. 本文包含一些常见的dp优化("√"表示下文会进行展示,没"√"表示暂 ...

  4. A Game of Thrones(12) - Eddard

    The summons(['sʌm(ə)nz]召唤:传票) came in the hour before the dawn, when the world was still and grey. A ...

  5. A Game of Thrones(3) - Daenerys

    Her brother held the gown up for her inspection. “This is beauty. Touch it. Go on. Caress(爱抚,抚抱) the ...

  6. 【noip模拟赛 sword,zero,2048】 题解

    1.光剑 (sword.pas/c/cpp) [题目描述] 小林和亮亮各有一把光剑,长度分别为 a 和 b,他们拿光剑进行比试.每一回合,长光剑会砍向短光剑,砍完后,短光剑完好无损,而长光剑则被截成两 ...

  7. UVA 11383 Golden Tiger Claw 题解

    题目 --> 题解 其实就是一个KM的板子 KM算法在进行中, 需要满足两个点的顶标值之和大于等于两点之间的边权, 所以进行一次KM即可. KM之后, 顶标之和就是最小的.因为如果不是最小的,就 ...

  8. Golden Tiger Claw,题解

    题目链接 题目: 题意: 找到和最小的两个序列a,b满足对于任意i,j有a[i]+b[j]>=c[i][j](矩阵c给出). 分析: 首先很容易看出来要使这题要用KM算法,为啥呢?因为要最小化a ...

  9. Sword框架解析——知识采集流程页面初始化

    Sword框架解析——知识采集流程页面初始化 Sword框架解析知识采集流程页面初始化 问题解答流程采集新增页面初始化 1后台t_xt_gnzy表和BLH类 2BLH类的写法前台目录树代码 3登录系统 ...

  10. 2016 Multi-University Training Contest 4 部分题解

    1001,官方题解是直接dp,首先dp[i]表示到i位置的种类数,它首先应该等于dp[i-1],(假设m是B串的长度)同时,如果(i-m+1)这个位置开始到i这个位置的这一串是和B串相同的,那么dp[ ...

随机推荐

  1. 【中英】【吴恩达课后测验】Course 5 - 序列模型 - 第一周测验

    [中英][吴恩达课后测验]Course 5 -序列模型 - 第一周测验 - 循环神经网络 上一篇:[课程4 - 第四周编程作业]※※※※※ [回到目录]※※※※※下一篇:[待撰写-课程5 -第一周编程 ...

  2. Java IO<1>File类

    java.io.File类 文件和文件目录路径的抽象表示形式,与平台无关 File 能新建.删除.重命名文件和目录,但 File 不能访问文件内容本身. 如果需要访问文件内容本身,则需要使用输入/输出 ...

  3. 题解:AT_arc073_d [ARC073F] Many Moves

    题目链接:link. 题意已经挺简易了,直接上思路吧. 我们设 \(f_{i,j}\) 表示当前在第 \(i\) 个时刻,一个棋子在 \(x_i\) 位置,另一个棋子在 \(j\) 位置的最小代价之和 ...

  4. Redhat 7.2 中文显示及中文输入法设置

    一.安装系统语言为中文(此步可以忽略)-1- 查看系统中文语言安装包1命令:yum list kde*chinese 结果:可用安装包 kde-l10n-Chinese.noarch Hint 1:y ...

  5. helm常用操作整理

    说明 下面是整理的日常常用的一些helm操作,后面会持续更新 下载chart到本地 helm repo add bitnami https://charts.bitnami.com/bitnami # ...

  6. 科学做Leetcode,拒绝思维懒惰

    思考题目10分钟左右完全没有思路可以看题解,不要一道题自己整个30分钟,还是不会 => 这种行为属于思维上的懒惰,我们不要做一个懒惰的人 看题解: 10分钟左右完全没有思路看题解 做完题目一定要 ...

  7. AEM6.5集成Redis详细步骤(附代码)

    一.环境准备 Redis 安装 2.配置 Redis 远程访问 二.AEM 端配置 1.添加 Redis 客户端依赖 在 AEM 项目的pom.xml中添加: <dependency> & ...

  8. [abc313 h/ex] Group Photo

    Ex - Group Photo 很牛的题 设\(A_0=A_{n+1}=INF\),那么对于每个\(B_i\)有\(B_i>\min(A_{i-1},A_i)\),所以考虑设\(C_i\)表示 ...

  9. mysql递归查询(父级,子集)

    ①查询父级 表: 先给表创建函数: 1 CREATE FUNCTION `getParentList`(rootId varchar(100)) 2 RETURNS varchar(1000) 3 B ...

  10. ORACLE--SQL日常问题和技巧1(列变行、自定义查询结构、将字符串分割为多条记录)

    1.ORACLE列变行加合计: 查询结果为 1 SELECT 2 nvl( F, '合计' ) F, 3 sum( S1 ) S1, 4 sum( S2 ) S2, 5 sum( S3 ) S3 6 ...