IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> (P5858 )「SWTR-03」Golden Sword(动态规划+单调队列优化) -> 正文阅读

[数据结构与算法](P5858 )「SWTR-03」Golden Sword(动态规划+单调队列优化)

题目链接:「SWTR-03」Golden Sword - 洛谷

分析:读完题很容易发现这是一个dp题,我们设f[i][j]表示加完第i种原料后还剩j种原料的最大耐久度之和,我们来看看f[i][j]可以由哪些状态来转移得到,很显然它是由加完第i-1种原料的一些状态得到的,现在我们来想想应该加完第i-1种原料剩下多少种原料才能转移得到f[i][j]呢?其实这个也不是很难想,首先f[i][j-1]这个肯定可以,我们直接加上第i种原料即可,其次f[i-1][j]也可以,我们可以先去掉一种原料然后再加上第i种原料,依次类推,f[i-1][j-1+s]也可以,无非就是我们先去掉s种原料再加上第i种原料罢了,最后别忘了加上当前原料的贡献,注意的是我们不能使剩余的原料个数大于w,当然这个也比较好判断。下面来看一下代码:(这个代码是一个超时代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
const int N=5e3+10;
ll f[N][N];//f[i][j]表示放完第i种原料后锅内还有j种原料的最大耐久度之和 
ll a[N];
int main()
{
	int n,w,s;
	cin>>n>>w>>s;
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	memset(f,-0x3f,sizeof f);
	f[0][0]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=min(w,i);j++)
		for(int k=j-1;k<=min(w,j-1+s);k++)
			f[i][j]=max(f[i][j],f[i-1][k]+a[i]*j);
	}
	ll ans=-0x3f3f3f3f;
	for(int i=1;i<=w;i++)
		ans=max(ans,f[n][i]);
	printf("%lld",ans);
	return 0;
}

注意:上述代码会超时,因为三重for循环,所以复杂度太高,现在我们来看看能不能对这道题目进行一下优化,我们先来看一下最里面的一层for循环,就是枚举f[i-1][j-1~j-1+s]然后找一个最大值,但是这个找最大值的过程我们是o(n)的,而且这个过程我们需要遍历多次,大家有没有发现这个问题似曾相识,就是滑动窗口的那个问题,每次给定一个窗口的范围,然后找这个窗口的最大值或者最小值,不知道这道题的同学可以看下我之前的博客,下面附上博客地址:滑动窗口(单调队列)_AC__dream的博客-CSDN博客

而这道题的优化方式与滑动窗口那道题非常像,唯一的不同就是这道题的查询区间不是固定的,但本质解法上是一模一样的,我们把最后两层for循环优化成一层for循环就可以通过这道题目了,特别需要注意的一点就是我们每次查找最大值之前都需要把队列清空,这点非常重要,就是这个点卡了我一天(+-+),就是希望大家注意一下吧,下面附上代码,希望大家好好理解一下,这种优化方式我觉得还是非常巧妙的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
const int N=5e3+10;
ll q[N],tt,hh;
ll f[N][N];//f[i][j]表示放完第i种原料后锅内还有j种原料的最大耐久度之和 
ll a[N];
int main()
{
	int n,w,s;
	cin>>n>>w>>s;
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	memset(f,-0x3f,sizeof f);
	f[0][0]=0;
	for(int i=1;i<=n;i++)
	{
		hh=tt=0;//一定不要忘记初始化
		for(int j=1,k=0;j<=min(w,i);j++)//单调队列优化 
		{
			while(k<=min(w,j-1+s))//把更新f[i][j]的f[i-1][k]全部入队列
			{
				while(hh<tt&&f[i-1][q[tt]]<=f[i-1][k]) tt--;
				q[++tt]=k++;
			}
			while(hh<tt&&q[hh+1]<j-1) hh++;
			f[i][j]=f[i-1][q[hh+1]]+a[i]*j;
		}
	}
	ll ans=-0x3f3f3f3f3f3f3f3f;
	for(int i=1;i<=w;i++)
		ans=max(ans,f[n][i]);
	printf("%lld",ans);
	return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-24 15:33:08  更:2022-02-24 15:34:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:22:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码