首页 > 其他分享 >[题解]P5858 Golden Sword

[题解]P5858 Golden Sword

时间:2024-03-26 22:55:06浏览次数:23  
标签:5010 maxx int 题解 P5858 long Sword max dp

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)。

优化

然而这份代码提交上去,能\(A\)大部分,但还有\(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;
}

标签:5010,maxx,int,题解,P5858,long,Sword,max,dp
From: https://www.cnblogs.com/Sinktank/p/18097587

相关文章

  • 启动应用程序出现dmrc.dll找不到问题解决
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个dmrc.dll文件(挑选合适的版本文件)把它放入......
  • 启动应用程序出现dmusic.dll找不到问题解决
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个dmusic.dll文件(挑选合适的版本文件)把它放......
  • 启动应用程序出现dot3hc.dll找不到问题解决
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个dot3hc.dll文件(挑选合适的版本文件)把它放......
  • 2024年3月26号题解
    EightII解题思路使用IDA*算法进行搜索,同时遍历所有高度中最小的,再保存dfs中的路径就可以了代码实现#include<sstream>#include<iostream>#include<algorithm>#include<cstring>#include<unordered_map>#include<queue>#include<set>usingnamespacestd;......
  • 联合省选 2024 题解
    魔法手杖考虑判定答案是否可以大于等于\(t\)。观察\(a_i\oplusx<t\)的情况,可以发现满足要求的\(x\)分为若干段:最高\(u\)位为\(a_i\oplust\)的最高\(u\)位;接下来这一位\(t\)为\(1\),且\(x\)取值为\(a_i\)这一位的取值;更低的位随意。这事实上相当于:我们往0......
  • AT_arc174_a [ARC174A] A Multiply的题解
    (一)注意到,\(c\)可能\(<1\)。主要考虑操作后的变化量。当\(c=1\)时,不会改变序列。当\(c>1\)时,和最大即为增加最多。那么求出最大子段和,再乘上\(c-1\)即为变化量。当\(c<1\)时,将序列每个数取反即可。(二)我因为不会最大字段和挂了3发。#include<bits/stdc+......
  • ARC 175 C 题解
    我们考虑经典套路,假设前\(i-1\)个数已经被确定。设\(f_k(x)\)表示\(a_k=x\)时\(\sum_{i=k+1}^n|\a_i-a_{i-1}\|\)的最小值。那么,\(a_i=x\)当且仅当\(x\)取最小值且\(|\x-a_{i-1}\|+f_i(x)\)为所有可能中的最小值。我们设集合\(I_k......
  • 【蓝桥杯省赛真题33】python单词排序 中小学青少年组蓝桥杯比赛 算法思维python编程省
     目录python单词排序一、题目要求1、编程实现2、输入输出二、算法分析三、程序编写四、程序说明五、运行结果六、考点分析七、 推荐资料1、蓝桥杯比赛2、考级资料3、其它资料python单词排序第十三届蓝桥杯青少年组python比赛省赛真题一、题目要求(注:input......
  • AT_arc174_b [ARC174B] Bought Review 题解
    题目翻译针对\(T\)个测试用例解决以下问题:在美食评论网站EatCocoder上,你可以评论餐厅的星级(从\(1\)到\(5\)的整数)。最初,由厨师长\(B\)管理的餐厅有\(A_i\)条\(i\)星级评价。(\(1≤i≤5\))厨师可以向EatCocoder管理部门行贿提供\(P_i\)日元,以获得一......
  • AT_arc174_a [ARC174A] A Multiply 题解
    题目翻译给你一个长度为\(N\)的整数序列,\(A=(A_1,A_2,…,A_N)\),和一个整数\(C\)。在执行以下操作最多一次后,找出A中元素的最大可能和:选择两个整数\(l\)和\(r\)(\(1≤l≤r≤N\)),将\(A_l,A_{l+1},…,A_r\)分别乘以\(C\)。算法法一(暴力)可以\(O_{(N^2)}\)暴力......