算法学习系列(六十):区间DP

目录

  • 引言
  • 区间合并模板
  • 一、石子合并
  • 二、环形石子合并
  • 三、能量项链

引言

关于这个区间 D P DP DP ,其实是有套路和模板的,题型的话也是变化不多,感觉就那几种,只不过有些题会用到高精度或者是要记录方案,所以整体来说还是比较容易的了,然后这种题型还是多见的为好,目前也只是会做这几道题。其实关于蓝桥杯只要你暴力都能打满,那么国三是稳了的,如果能做对大概两道题,那么就能拿国二,所以说搞这个 D P DP DP 也只是看能不能碰见做过类似的题目,现场解题我是不敢想了,太难的压根做不出来,但也不能完全不学,不是特别难的还是要学,万一出了那就是自己赚了,所以继续加油吧,另外感觉身体累了,也是要合理的休息的!


区间合并模板

memset(f, 0x3f, sizeof f);  //先全部初始化为非法状态 
for(int len = 1; len <= n; ++len)  // 确定r
{
    for(int l = 1; l + len - 1 <= n; ++l)  //确定l
    {
        int r = l + len - 1;
        if(l == r) f[l][r] = 0;  // 计算f[l][r]
        else  // 计算f[l][r]
        {
        	for(int k = l; k < r; ++k) f[l][r] = min(f[l][r], f[l][k] + f[k+1][r] + ...);
        }
    }
}

一、石子合并

标签:动态规划、区间DP

思路:这个区间 D P DP DP 其实用之前的分析法也是可以的,一般状态定义都是看经验,定义一个状态 f [ i ] [ j ] f[i][j] f[i][j] 代表合并 i ∼ j i \sim j ij 区间内的石子所要花费的最小的代价,状态计算也是跟那个 F l o y d Floyd Floyd 算法差不多,就是把这一个区间按照倒数第二步划分,也就是把 f [ i ] [ j ] f[i][j] f[i][j] 按照分界点划分为 f [ i ] [ k ] , f [ k + 1 ] [ j ] f[i][k],f[k+1][j] f[i][k],f[k+1][j] ,然后再进行取最小值。两堆石子合并所花费的最小的代价,就是合并成两堆石子各自的最小代价加上这两堆石子总的代价,前面的也就是 f [ i ] [ k ] , f [ k + 1 ] [ j ] f[i][k],f[k+1][j] f[i][k],f[k+1][j] 了,后面的可以直接拿前缀和来做即可。那么状态转移方程就为 f [ l ] [ r ] = m i n ( f [ l ] [ r ] , f [ l ] [ k ] + f [ k + 1 ] [ r ] + s [ r ] − s [ l − 1 ] ) f[l][r] = min(f[l][r], f[l][k]+f[k+1][r] + s[r] - s[l-1]) f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]s[l1]) ,然后初始的状态 f [ i ] [ i ] f[i][i] f[i][i] 的值为 0 0 0 ,然后其余的都是非法的,并且该题求的是最小值,所以初始化为正无穷即可。剩余的就按照模板即可。

题目描述:

设有 N 堆石子排成一排,其编号为 1,2,3,…,N。

每堆石子有一定的质量,可以用一个整数来描述,现在要将这 N 堆石子合并成为一堆。

每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻,合并时由于选
择的顺序不同,合并的总代价也不相同。

例如有 4 堆石子分别为 1 3 5 2, 我们可以先合并 1、2 堆,代价为 4,得到 4 5 2, 又合并 1、2 堆,代价为 9,得到 9 2 ,再合
并得到 11,总代价为 4+9+11=24;

如果第二步是先合并 2、3 堆,则代价为 7,得到 4 7,最后一次合并代价为 11,总代价为 4+7+11=22。

问题是:找出一种合理的方法,使总的代价最小,输出最小代价。

输入格式
第一行一个数 N 表示石子的堆数 N。

第二行 N 个数,表示每堆石子的质量(均不超过 1000)。

输出格式
输出一个整数,表示最小代价。

数据范围
1≤N≤300
输入样例:
4
1 3 5 2
输出样例:
22

示例代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y second

const int N = 310, M = N, INF = 0x3f3f3f3f;

int n, m;
int s[N], f[N][N];

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
	cin >> n;
	for(int i = 1; i <= n; ++i) cin >> s[i], s[i] += s[i-1];
	
	memset(f, 0x3f, sizeof f);
	for(int len = 1; len <= n; ++len)
	{
		for(int l = 1; l + len - 1 <= n; ++l)
		{
			int r = l + len - 1;
			if(l == r) f[l][r] = 0;
			else
			{
			    for(int k = l; k < r; ++k) f[l][r] = min(f[l][r], f[l][k] + f[k+1][r] + s[r] - s[l-1]);
			}
		}
	}
	
	cout << f[1][n] << endl;
	
	return 0;
}

二、环形石子合并

标签:DP、区间DP、环形区间DP

思路:这道题跟上一道题唯一的不同就是该题的石子是环形的,不是链形的,解决的办法都是在该链的基础上在追加一条链,然后在此基础上做区间 D P DP DP ,最后再枚举每 n n n 堆石子找最值。为什么这样做是正确的呢,如下图所示,如果我们把圆圈看作石子,连边看作是石子之间的合并,那么必然会连 n − 1 n-1 n1 条边,那么肯定会如下图所示会有一个缺口,我们把其展开就是一条长度为 n n n 的链了,那么我们直接枚举这个缺口,也就是在 2 n 2n 2n 的长度下做区间为 n n n 的区间合并,最后再枚举所有长度为 n n n 的区间的结果即可。其余的初始化等细节,详情见代码。
在这里插入图片描述

题目描述:

将 n 堆石子绕圆形操场排放,现要将石子有序地合并成一堆。

规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该次合并的得分。

请编写一个程序,读入堆数 n 及每堆的石子数,并进行如下计算:

选择一种合并石子的方案,使得做 n−1 次合并得分总和最大。选择一种合并石子的方案,使得做 n−1 次合并得分总和最小。

输入格式
第一行包含整数 n,表示共有 n 堆石子。

第二行包含 n 个整数,分别表示每堆石子的数量。

输出格式
输出共两行:

第一行为合并得分总和最小值,

第二行为合并得分总和最大值。

数据范围
1≤n≤200
输入样例:
4
4 5 9 4
输出样例:
43
54

示例代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y second

const int N = 410, M = N, INF = 0x3f3f3f3f;

int n, m;
int w[N], s[N];
int f[N][N], g[N][N];

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		cin >> w[i];
		w[i+n] = w[i];
	}
	for(int i = 1; i <= n * 2; ++i) s[i] = w[i] + s[i-1];
	
	memset(f, 0x3f, sizeof f);
	memset(g, -0x3f, sizeof g);
	
	for(int len = 1; len <= n; ++len)
	{
		for(int l = 1; l + len - 1 <= n * 2; ++l)
		{
			int r = l + len - 1;
			if(l == r) f[l][r] = g[l][r] = 0;
			else
			{
			    for(int k = l; k < r; ++k)
    			{
    				f[l][r] = min(f[l][r], f[l][k] + f[k+1][r] + s[r] - s[l-1]);
    				g[l][r] = max(g[l][r], g[l][k] + g[k+1][r] + s[r] - s[l-1]);
    			}
			}
		}
	}
	
	int r1 = INF, r2 = -INF;
	for(int i = 1; i <= n; ++i)
	{
		r1 = min(r1, f[i][i+n-1]);
		r2 = max(r2, g[i][i+n-1]);
	}
	
	cout << r1 << endl << r2 << endl;
	
	return 0;
}

三、能量项链

标签:DP、区间DP、破环成链

思路:这道题其实跟上一道题是差不多的, 区别就是 l e n len len 最小从 2 2 2 变成 3 3 3 了,并且总的长度变为了 n + 1 n+1 n+1 ,由于题目特性,两颗珠子根据首尾也能合并成一个珠子。所以最终的结果就是 f [ i ] [ i + n ] f[i][i+n] f[i][i+n] 里选一个,因为 l e n len len 最小是 3 3 3 ,所以 l < k < r l<k<r l<k<r ,状态转移方程为 ∑ k = l + 1 k = r − 1 f [ l ] [ r ] = m a x ( f [ l ] [ r ] , f [ l ] [ k ] + f [ k ] [ r ] + w [ l ] ∗ w [ k ] ∗ w [ r ] ) \sum_{k=l+1}^{k=r-1} f[l][r] = max(f[l][r], f[l][k] + f[k][r] + w[l] * w[k] * w[r]) k=l+1k=r1f[l][r]=max(f[l][r],f[l][k]+f[k][r]+w[l]w[k]w[r]) 。其余的就是模板,细节见代码。

题目描述:

在 Mars 星球上,每个 Mars 人都随身佩带着一串能量项链,在项链上有 N 颗能量珠。

能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数。

并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。

因为只有这样,通过吸盘(吸盘是 Mars 人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被
吸盘吸收的能量。

如果前一颗能量珠的头标记为 m,尾标记为 r,后一颗能量珠的头标记为 r,尾标记为 n,则聚合后释放的能量为 m×r×n
(Mars 单位),
新产生的珠子的头标记为 m,尾标记为 n。

需要时,Mars 人就用吸盘夹住相邻的两颗珠子,通过聚合得到能量,直到项链上只剩下一颗珠子为止。

显然,不同的聚合顺序得到的总能量是不同的,请你设计一个聚合顺序,使一串项链释放出的总能量最大。

例如:设 N=4,4 颗珠子的头标记与尾标记依次为 (2,3)(3,5)(5,10)(10,2)。

我们用记号 ⊕ 表示两颗珠子的聚合操作,(j⊕k) 表示第 j,k 两颗珠子聚合后所释放的能量。则

第 4、1 两颗珠子聚合后释放的能量为:(4⊕1)=10×2×3=60。

这一串项链可以得到最优值的一个聚合顺序所释放的总能量为 ((4⊕1)⊕2)⊕3)=10×2×3+10×3×5+10×5×10=710。

输入格式
输入的第一行是一个正整数 N,表示项链上珠子的个数。

第二行是 N 个用空格隔开的正整数,所有的数均不超过 1000,第 i 个数为第 i 颗珠子的头标记,当 i<N 时,第 i 颗珠子的尾标记
应该等于第 i+1 颗珠子的头标记,第 N 颗珠子的尾标记应该等于第 1 颗珠子的头标记。

至于珠子的顺序,你可以这样确定:将项链放到桌面上,不要出现交叉,随意指定第一颗珠子,然后按顺时针方向确定其他珠子的顺序。

输出格式
输出只有一行,是一个正整数 E,为一个最优聚合顺序所释放的总能量。

数据范围
4≤N≤100,1≤E≤2.1×109
输入样例:
4
2 3 5 10
输出样例:
710

示例代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;
#define x first
#define y second

const int N = 210, M = N, INF = 0x3f3f3f3f;

int n, m;
int w[N], f[N][N]; 

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
	cin >> n;
	for(int i = 1; i <= n; ++i) cin >> w[i], w[i+n] = w[i];
	
	memset(f, -0x3f, sizeof f);
	for(int len = 1; len <= n + 1; ++len)
	{
		for(int l = 1; l + len - 1 <= n * 2; ++l)
		{
			int r = l + len - 1;
			if(r - l + 1 < 3) f[l][r] = 0;
			else
			{
			    for(int k = l + 1; k < r; ++k)
    			{
    				f[l][r] = max(f[l][r], f[l][k] + f[k][r] + w[l] * w[k] * w[r]);
    			}
			}
		}
	}
	
	int res = 0;
	for(int i = 1; i <= n; ++i)
	{
		res = max(res, f[i][i+n]);
	}
	
	cout << res << endl;
	
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/617838.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么你总是买不到心仪的房?可能是因为你忽略了这些!

​在人生的旅途中&#xff0c;过多的选择有时并无益处。当选择变得繁多&#xff0c;我们往往容易迷失方向&#xff0c;渴望拥有所有&#xff0c;但最终可能一无所获。 对于迫切需要购房的人来说&#xff0c;他们常常面临这样的困境&#xff1a;被各种声音和推荐所包围&#xf…

STM32窗口看门狗的操作

STM32的窗口看门狗的主要功能是&#xff0c;程序过早的喂狗还有太晚喂狗&#xff0c;都会触发单片机重启&#xff0c;就是有一个时间段&#xff0c;在这个时间段内喂狗才不会触发单片机重启。 下面我就总结一下窗口看门狗的设置过程&#xff1a; 第一步&#xff1a;开启窗口看…

搭建本地yum仓库

步骤 找个地方存你的rpm包 #我创建了一个rpm文件夹存放我的rpm包 makdir -p /opt/repo/rpmcreaterepo 这个很重要&#xff0c;一定要安装 # 我的能连外网&#xff0c;所以直接yum安装&#xff0c;你的自己想办法 yum install createrepo -y创建repodata 安装了createrepo后…

day001 ~如何修改主机名

命令行方式设置主机名 # 这个很重要&#xff01;用命令改方便些 hostnamectl set-hostname ocloud-252 #查询&#xff0c;exit或logout重新登录后发现主机名换掉 hostname nmtui方式修改 nmtui 在工作中,如果机器很多,最好修改主机名做好标识不至于弄混,方便管理.

WEB后端复习——监听器、过滤器

Listener监听器 是Servlet规范中定义的一种特殊类&#xff0c;它用于监听web应用程序中的ServletContext, HttpSession和ServletRequest等域对象的创建与销毁事件&#xff0c;以及监听这些域对象中的属性发生修改的事件。 注解WebListener 1.ServletContextListener 监听Serv…

Windows使用cowaxess(goaccess)分析Nginx日志

原文网址&#xff1a;Windows使用cowaxess(goaccess)分析Nginx日志_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Windows安装cowaxess来分析Nginx的access.log日志的方法。 cowaxess是goaccess的Windows版本&#xff0c;cowaxess底层会调用goaccess。 GoAccess 是一个专门用来…

uniapp获取当前位置及检测授权状态——支持App、微信小程序

uniapp获取当前位置检测及定位权限——支持App、微信小程序 首先&#xff0c;祝天下母亲&#xff0c;节日快乐~ 文章目录 uniapp获取当前位置检测及定位权限——支持App、微信小程序效果图新增 兼容小程序方法manifest Tips&#xff1a; 上一篇介绍 App端 uniapp获取当前位置及…

# 电脑突然连接不上网络了,怎么办?

电脑突然连接不上网络了&#xff0c;怎么办&#xff1f; 一、原因分析&#xff1a; 1、IP 地址冲突 2、DNS 解析出现问题。 3、电脑网络设置是否打开了【移动热点】或【飞行模式】。 4、【WLAN AutoConfig】服务是否打开。 5、无线网卡驱动损坏。 6、检查 WIFI 开关是否…

新闻资讯微信小程序开发后端+php【附源码,文档说明】

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

1060: 无向图的最大度计算

解法&#xff1a; #include<iostream> #include<vector> using namespace std; int arr[100][100]; int main() {int n, max 0;cin >> n;vector<int> sum(n, 0);for (int i 0; i < n; i) {for (int j 0; j < n; j) {cin >> arr[i][j];…

Web UI自动化测试--PO模式

没有PO实现的测试用例的问题: 重用性低:登录功能重复可维护性差:数据和代码混合可读性差:元素定位方法杂乱(id、xpath、css混杂)可读性差:不易识别操作的含义(特别是css和xpath语法)可维护性差:如果某个元素的属性改了,你要更改多次PO(Page Object Model)页面对象模型…

零基础学MySQL

1. 零基础学MySQL 1.1 数据库简介 1.1.1 数据库三层结构 1. 所谓安装Mysql数据库&#xff0c;就是在主机安装一个数据库管理系统(DBMS)&#xff0c;这个管理程序可以管理多个数据库。DBMS(database manage system) 2. 一个数据库中可以创建多个表,以保存数据(信息)。 3. 数据…

ASP.NET一种多商家网络商店的设计与实现

摘 要 21世纪是网络的世纪&#xff0c;电子商务随之将成为主流商业模式&#xff0c;多商家网络商店系统就是一个C2C型的电子商务系统。本文详细论述了采用ASP.NET 2005 和 SQL Server 2000等技术实现的一个多商家网络商店的过程。论文首先阐述了本设计题目的选题意义、背景&a…

其他的 框架安全:Apache Solr 远程代码漏洞.(CVE-2019-0193)

什么是 Apache Solr Apache Solr是一个开源的搜索服务&#xff0c;便用Java语言开发&#xff0c;主要基于 HTTP 和ApacheLucene 实现的。Sor是一个高性能&#xff0c;采用Java5开发&#xff0c;基于Lucene的全文搜索服务器。 目录&#xff1a; 什么是 Apache Solr 生成的漏…

Multisim 14 常见电子仪器的使用和Multisim的使用

multisim multisim&#xff0c;即电子电路仿真设计软件。Multisim是美国国家仪器&#xff08;NI&#xff09;有限公司推出的以Windows为基础的仿真工具&#xff0c;适用于板级的模拟/数字电路板的设计工作。它包含了电路原理图的图形输入、电路硬件描述语言输入方式&#xff0…

【Python项目】基于大数据的【电影市场预测分析】

技术简介&#xff1a;使用Python技术、B/S架构、MYSQL数据库等实现。 系统简介&#xff1a;系统都需要简单的安全登陆检查&#xff0c;在登陆成功之后要进行在映电影的分析、票房分析、电影数据等功能相关性的数据统计&#xff0c;为了使用方便这些统计型的数据使用图表来进行表…

C++高精度算法-加法

引子 在C++的运算中,难免会出现很大很大的数,下面是各个关键字的表示范围 但是如果要表示的数超过了long long可以表示的最大值( 2 64 2^{64} 264-1) 怎么办呢? 如果强制表示,就会溢出,这里的溢出大家可以自行百度,反正就是会出一些-5665434之类的数 现在,就要切入正…

Git 的原理与使用(上)

Git是一个分布式版本控制系统&#xff0c;它被广泛用于协作开发和管理软件项目。开发人员可以通过Git来跟踪文件的变化、协调工作、并管理项目的不同版本。 Git允许用户在不同的分支上开发新功能&#xff0c;然后合并这些分支并确保团队成员之间的工作协调一致。此外&#xff…

【大模型赋能开发者】海云安入选数世咨询LLM驱动数字安全2024——AI安全系列报告

近日&#xff0c;国内知名数字产业领域第三方调研咨询机构数世咨询发布了LLM驱动数字安全2024——AI安全系列报告。报告通过调研、公开信息收集等方式对目前十余家已具备LLM相关的应用能力安全厂商对比分析出了这一领域当前的产业现状并进行了各厂商的能力展示。 海云安凭借近…

易图讯三维电子沙盘-大数据处理服务

易图讯科技10名高级大数据工程师&#xff0c;高效、快速进行POI、DEM、高清卫星影像、地形地貌、路网、矢量地图等海量大数据处理服务。 免费专业提供POI、AOI、DEM、高清卫星影像、地形地貌、路网、矢量地图等海量大数据处理服务。 1年更新2次POI、高清卫星影像。