区间dp 笔记

区间dp一般是先枚举区间长度,再枚举左端点,再枚举分界点,时间复杂度为n^{3}

环形石子合并

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

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

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

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

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

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

输出格式

输出共两行:

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

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

数据范围

1≤n≤200

输入样例:
4
4 5 9 4
输出样例:
43
54

 考了把环拆成链,把两个数组拼在一起可以达成 类环 的效果

比如 1 2 3 4 1 2 3 4

环可以是[1 2 3 4] [2 3 4 1] [3 4 1 2] [4 1 2 3]

这样就可以在石子合并的基础上增加微量时间复杂度的情况下做这道题了

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef long long ll;
typedef pair<ll, int> PII;

const int N = 410;

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

int main()
{
	IOS
	cin >> n;
	for(int i = 1; i <= n; i ++)
	{
		cin >> w[i];
		w[i + n] = w[i];
	}
	for(int i = 1; i <= n + n; i ++)
	{
		s[i] = s[i - 1] + w[i];
	}
	
	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 + n; l ++)
		{
			int r = l + len - 1;
			if(len == 1)
			{
				f[l][r] = g[l][r] = 0;
				continue;
			}
			
			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 maxn = -2e9, minx = 2e9;
	for(int i = 1; i <= n; i ++)
	{
		maxn = max(maxn, g[i][i + n - 1]);
		minx = min(minx, f[i][i + n - 1]);
	}
	cout << minx << endl;
	cout << maxn;
	
	return 0;
} 

能量项链

在 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×1e9

输入样例:
4
2 3 5 10
输出样例:
710

和上一题几乎一模一样

可以先枚举长度,再枚举首位端点,再枚举连接点

 我写的代码不太一样,但结果都是一样的

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef long long ll;
typedef pair<ll, int> PII;

const int N = 210;

int n;
int w[N];
ll f[N][N];

int main()
{
	IOS
	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; len ++)
	{
		for(int l = 1; l + len - 1 <= n + n; l ++)
		{
			int r = l + len - 1;
			if(len == 1)
			{
				f[l][r] = 0;
				continue;
			}
			
			for(int k = l; k < r; k ++)
			{
				f[l][r] = max(f[l][r], f[l][k] + f[k + 1][r] + w[l] * w[k + 1] * w[r + 1]);
			}
		}
	}
	
	ll ans = -2e18;
	for(int i = 1; i <= n; i ++)
	{
	    ans = max(ans, f[i][i + n - 1]);
	}
	cout << ans;
	
	return 0;
} 

加分二叉树

设一个 n 个节点的二叉树 tree 的中序遍历为(1,2,3,…,n),其中数字 1,2,3,…,n 为节点编号。

每个节点都有一个分数(均为正整数),记第 i 个节点的分数为 di,tree 及它的每个子树都有一个加分,任一棵子树 subtree(也包含 tree 本身)的加分计算方法如下:     

subtree的左子树的加分 × subtree的右子树的加分 + subtree的根的分数 

若某个子树为空,规定其加分为 1。

叶子的加分就是叶节点本身的分数,不考虑它的空子树。

试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树 tree。

要求输出: 

(1)tree的最高加分 

(2)tree的前序遍历

输入格式

第 1 行:一个整数 n,为节点个数。 

第 2 行:n 个用空格隔开的整数,为每个节点的分数(0<分数<100)。

输出格式

第 1 行:一个整数,为最高加分(结果不会超过int范围)。     

第 2 行:n 个用空格隔开的整数,为该树的前序遍历。如果存在多种方案,则输出字典序最小的方案。

数据范围

n<30

输入样例:
5
5 7 1 2 10
输出样例:
145
3 1 2 4 5

 中序遍历一个数左边都是左子树的部分,一个数右边都是右子树的部分

所以可以用f[l, r]表示[l, r]区间内所有子树的最大值,去枚举每个点当根节点

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef long long ll;
typedef pair<ll, int> PII;

const int N = 40;

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

void dfs(int l, int r)
{
    if(l > r)return;
    int t = g[l][r];
    cout << t << ' ';
    dfs(l, t - 1);
    dfs(t + 1, r);
}

int main()
{
	IOS
	cin >> n;
	for(int i = 1; i <= n; i ++)cin >> w[i];
	
	for(int len = 1; len <= n; len ++)
	{
		for(int l = 1; l + len - 1 <= n; l ++)
		{
			int r = l + len - 1;
			if(len == 1)
			{
				f[l][r] = w[l];
				g[l][r] = l;
				continue;
			}
			
			for(int k = l; k <= r; k ++)
			{
				int left = k == l ? 1 : f[l][k - 1];
				int right = k == r ? 1 : f[k + 1][r];
				int score = left * right + w[k];
				if(f[l][r] < score)
				{
					f[l][r] = score;
					g[l][r] = k;
				}
			}
		}
	}
	
	cout << f[1][n] << endl;
	dfs(1, n);
	
	return 0;
}

凸多边形的划分

给定一个具有 N 个顶点的凸多边形,将顶点从 1 至 N 标号,每个顶点的权值都是一个正整数。

将这个凸多边形划分成 N−2 个互不相交的三角形,对于每个三角形,其三个顶点的权值相乘都可得到一个权值乘积,试求所有三角形的顶点权值乘积之和至少为多少。

输入格式

第一行包含整数 N,表示顶点数量。

第二行包含 N个整数,依次为顶点 1 至顶点 N 的权值。

输出格式

输出仅一行,为所有三角形的顶点权值乘积之和的最小值。

数据范围

N≤50,
数据保证所有顶点的权值都小于1e9

输入样例:
5
121 122 123 245 231
输出样例:
12214884

 可以发现每条边只会参与一个三角形的构成

以1-n这条边为底,共有n-2种选法,设选了k这个点为顶点,那左边1~k和右面k~n两个区域明显是相互独立的,这就构成了区间dp的基础

枚举选顶点是哪个即可

这题虽然也是环但不需要拼起来,因为每个边只参与一次,选1 - n还是选2 - n+1都是一样的

另外需要用到高精度,可以先当成不需要高精度的写出来,再改成高精度,这样轻松一点

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef long long ll;
typedef pair<ll, int> PII;

const int N = 55, M = 35, INF = 2e9;

int n;
int w[N];
ll f[N][N][M];//f[l,r]表示以l、r两点为边,以中间的一个顶点作为分界线 

void add(ll a[], ll b[])
{
	ll tmp[M] = {0};
	ll t = 0;
	for(int i = 0; i < M; i ++)
	{
		t += a[i] + b[i];
		tmp[i] = t % 10;
		t /= 10;
	}
	memcpy(a, tmp, sizeof tmp);
}

void mul(ll a[], ll b)
{
	ll tmp[M] = {0};
	ll t = 0;
	for(int i = 0; i < M; i ++)
	{
		t += a[i] * b;
		tmp[i] = t % 10;
		t /= 10;
	}
	memcpy(a, tmp, sizeof tmp);
}

int cmp(ll a[], ll b[])
{
	for(int i = M - 1; i >= 0; i --)
	{
		if(a[i] > b[i])return 1;
		if(a[i] < b[i])return -1;
	}
	return 0;
}

void print(ll a[])
{
	ll t = M - 1;
	while(t && !a[t])t --;
	for(int i = t; i >= 0; i --)cout << a[i];
	cout << endl;
}

int main()
{
	IOS
	cin >> n;
	for(int i = 1; i <= n; i ++)cin >> w[i];
	
	ll tmp[M];
	for(int len = 3; len <= n; len ++)
	{
		for(int l = 1; l + len - 1 <= n; l ++)
		{
			int r = l + len - 1;
			//f[l][r] = INF;
			f[l][r][M - 1] = 1;
			
			for(int k = l + 1; k < r; k ++)
			{
				memset(tmp, 0, sizeof tmp);
				tmp[0] = w[l];
				mul(tmp, w[r]);
				mul(tmp, w[k]);
				add(tmp, f[l][k]);
				add(tmp, f[k][r]);
				if(cmp(tmp, f[l][r]) < 0)
				{
					memcpy(f[l][r], tmp, sizeof tmp);
				}
				//f[l][r] = min(f[l][r], f[l][k] + f[k][r] + w[l] * w[r] * w[k]);
			}
		}
	}
	//cout << f[1][n];
	print(f[1][n]);
	
	return 0;
}

棋盘分割

将一个 8×8 的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了 (n−1)次后,连同最后剩下的矩形棋盘共有 n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)

1191_1.jpg

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。

现在需要把棋盘按上述规则分割成 n 块矩形棋盘,并使各矩形棋盘总分的均方差最小。

均方差

formula.png

 ,其中平均值

lala.png

 ,xi 为第 i 块矩形棋盘的总分。

请编程对给出的棋盘及 n,求出均方差的最小值。

输入格式

第 1 行为一个整数 n。

第 2 行至第 9 行每行为 8 个小于 100 的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。

输出格式

输出最小均方差值(四舍五入精确到小数点后三位)。

数据范围

1<n<15

输入样例:
3
1 1 1 1 1 1 1 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0
1 1 1 1 1 1 0 3
输出样例:
1.633

 f[x1][y1][x2][y1][k]表示左上角的点为(x1,y1),右下角的点为(x2,y2),这块区域要被分位k个点,表示均方差平方的最小值

由题可得n确定后平均值X也能确定

枚举时考虑横着切还是竖着切,切的时候考虑是留上边还是下边、左边还是右边

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef long long ll;
typedef pair<ll, int> PII;

const int N = 9, M = 15, INF = 2e9;

int n, m = 8;
int s[N][N];
double f[N][N][N][N][M];
double X;

double get(int x1, int y1, int x2, int y2)
{
	double res = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1] - X;
	return res * res / n;
}

double dp(int x1, int y1, int x2, int y2, int k)
{
	double &v = f[x1][y1][x2][y2][k];
	if(v >= 0)return v;
	if(k == 1)return get(x1, y1, x2, y2);
	
	v = INF;
	for(int i = x1; i < x2; i ++)
	{
		v = min(v, dp(x1, y1, i, y2, k - 1) + get(i + 1, y1, x2, y2));
		v = min(v, get(x1, y1, i, y2) + dp(i + 1, y1, x2, y2, k - 1));
	}
	for(int j = y1; j < y2; j ++)
	{
		v = min(v, dp(x1, y1, x2, j, k - 1) + get(x1, j + 1, x2, y2));
		v = min(v, get(x1, y1, x2, y2) + dp(x1, j + 1, x2, y2, k - 1)); 
	}
	return v;
}

int main()
{
	//IOS
	cin >> n;
	for(int i = 1; i <= m; i ++)
	{
		for(int j = 1; j <= m; j ++)
		{
			cin >> s[i][j];
			s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
		}
	}
	X = (double)s[m][m] / n;
	
	memset(f, -1, sizeof f);
	double t = dp(1, 1, m, m, n);
	printf("%.3lf", sqrt(t));
	
	return 0;
}

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

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

相关文章

qt学习:串口

头文件 #include <QSerialPort> #include <QSerialPortInfo> 模块 QT core gui serialport 编程步骤 配置一个ui界面&#xff0c;五个QComboBox和一个按钮和一个QTextEdit 添加一个成员 private:QSerialPort *serial; 在构造函数中初始化ui端口列表和…

【数据结构和算法】--- 基于c语言排序算法的实现(2)

目录 一、交换排序1.1 冒泡排序1.2 快速排序1.2.1 hoare法1.2.2 挖坑法1.2.3 前后指针法 1.3 快速排序优化1.3.1 三数取中法选key1.3.2 递归到小的子区间使用插入排序 1.4 快排非递归版 二、归并排序2.1 归并排序2.1.1 递归版2.1.2 非递归版 一、交换排序 基本思想&#xff1a…

hexo 博客搭建以及踩雷总结

搭建时的坑 文章置顶 安装一下这个依赖 npm install hexo-generator-topindex --save然后再文章的上面设置 top: number&#xff0c;数字越大&#xff0c;权重越大&#xff0c;也就是越靠顶部 hexo 每次推送 nginx 都访问不到 宝塔自带的 nginx 的 config 里默认的角色是 …

磁盘分区和挂载

一、分区概念 1、基本概念 (1) 一块硬盘最多只能有4个主分区 (2) 其中一个(且最多只能有一个)主分区能作为扩展分区,而扩展分区不能写入数据,只能包含逻辑分区 2、格式化 分区之后的磁盘并不能直接使用&#xff0c;而是需要先进行格式化&#xff0c;又称为逻辑格式化。它是指…

掌握Go的加密技术:crypto/rsa库的高效使用指南

掌握Go的加密技术&#xff1a;crypto/rsa库的高效使用指南 引言crypto/rsa 库概览RSA 加密算法基本原理crypto/rsa 库的功能和应用 安装和基本设置在 Go 项目中引入 crypto/rsa 库基本环境设置和配置 密钥生成与管理生成 RSA 密钥对密钥存储和管理 加密和解密操作使用 RSA 加密…

【HTML+CSS】使用CSS中的Position与z-index轻松实现一个简单的自定义标题栏效果

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起学习和进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&a…

【数据结构与算法】【小白也能学的数据结构与算法】递归 分治 迭代 动态规划 无从下手?一文通!!!

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

【计算机网络】Web HTTP

Web和HTTP HTTP 超文本传输协议 HyperText Transfer Protocol HTTP使用TCP作为支撑传输协议 由一个客户程序和一个服务器程序实现一些常见名词。。。无状态协议 stateless protocol 不保存关于客户的任何信息非持续/持续链接 non-persistent con…

【十三】【C++】vector简单实现

代码实现 /*vector类简单实现*/ #if 1 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std; #include <vector> #include <algorithm> #include <crtdbg.h> #include <assert.h> #include <string.h>namespace MyVe…

寒假作业2024.2.11

请使用递归实现n! #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <unistd.h> int fun(int n) {if (n0) {return 1;} else {return n*fun(n-1);} } int main(int argc, const char *argv[]) {int n…

嵌入式系统学习指南:从入门到精通

如今嵌入式系统已经广泛应用于工控、消费电子、汽车电子、医疗设备等多个领域。越来越多的IT工程师选择进入嵌入式系统行业。那么作为新手,如何系统地学习嵌入式知识,从入门到精通呢?本文将为大家提供一份简单的自学路线。&#xff08;个人观点&#xff0c;仅供参考&#xff0…

代码随想录 Leetcode55. 跳跃游戏

题目&#xff1a; 代码(首刷自解 2024年2月9日&#xff09;&#xff1a; class Solution { public:bool canJump(vector<int>& nums) {int noz 0;for (int i nums.size() - 2; i > 0; --i) {if (nums[i] 0) {noz;continue;} else {if (nums[i] > noz) noz …

vtkActor 设置特定图层 显示及置顶显示

问题&#xff0c;有时我们需要显示某个 Actor 在相机最前面&#xff0c;可以遮盖后面的物体;显示在顶层有点不准确&#xff1b;因为这个还相机位置也有关系&#xff1b; 这里讲三种情况&#xff1a; 1. 设置 Mapper 顶层&#xff0c;尝试了一下&#xff0c;可以用于某些场景&…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(12)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述&#xff08;11&#xff09; 4.2 PCIe体系结构的组成部件 PCIe总线作为处理器系统的局部总线&#xff0c;其作用与PCI总线类似&#xff0c;主要目的是为了连接处理器系统中的外部设备…

前后端分离nodejs+vue流浪狗宠物领养公益网站

1.发现公益&#xff1a;主要是根据社会上的调研&#xff0c;来收集的社会上有关流浪狗的公益活动&#xff0c;发布在公益网站上能被更多人发现&#xff0c;主要让更多人能参与到公益活动中来&#xff0c;并调动群众的同情心和爱心&#xff0c;借此希望在养宠物的主人能避免自己…

直播app开发,技术驱动的实时互动新纪元

随着互联网技术的快速发展&#xff0c;直播已成为我们日常生活的重要组成部分。从娱乐、教育到商业活动&#xff0c;直播的广泛应用正在改变着我们的生活和工作方式。在这一变革中&#xff0c;直播开发扮演着至关重要的角色。本文将探讨直播开发的核心理念、技术挑战以及未来的…

【EAI 017】Interactive Language: Talking to Robots in Real Time

论文标题&#xff1a;Interactive Language: Talking to Robots in Real Time 论文作者&#xff1a;Corey Lynch, Ayzaan Wahid, Jonathan Tompson Tianli Ding, James Betker, Robert Baruch, Travis Armstrong, Pete Florence 作者单位&#xff1a;Robotics at Google 论文原…

林浩然与杨凌云的Java世界奇遇记:垃圾回收大冒险

林浩然与杨凌云的Java世界奇遇记&#xff1a;垃圾回收大冒险 The Java Adventure Chronicles of Lin Haoran and Yang Lingyun: Garbage Collection Odyssey 在一个充满0和1代码森林的世界里&#xff0c;住着两位勇敢的程序员侠侣——林浩然和杨凌云。林浩然是个身怀Java绝技的…

k8s -ingress

概念 Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由&#xff0c;ingress能代理集群为内部的网络&#xff0c;将集群外部的HTTP/HTTPS网络请求转发至不同的service&#xff0c;其本质就是创建一个NodePort类型的svc,和一个nginx 组成 k8s中的ingress 其实是指…

【万题详解】洛谷P1282 多米诺骨牌

题目 链接——题目在这里&#xff01;&#xff01;&#xff01; 多米诺骨牌由上下 22 个方块组成&#xff0c;每个方块中有 1∼6 个点。现有排成行的上方块中点数之和记为 S1​&#xff0c;下方块中点数之和记为 S2​&#xff0c;它们的差为 ∣∣S1​−S2​。如图S161119&…