C++OJ题经验总结(竞赛)3

注意:本篇标红字段均是可纳为己用的经验条。
OJ题知识归属:

1、第一题:动态规划 -> 区间dp(基于区间的左右端点,分情况讨论)

2、第二题:动态规划 -> 区间dp(基于区间的左右端点,分情况讨论)

3、第三题:动态规划 -> 区间dp(基于区间上某⼀点,划分成左右区间讨论)(线形)

4、第四题:动态规划 -> 区间dp(基于区间上某⼀点,划分成左右区间讨论)(环形)
OJ题来源:洛谷

OJ题名:回文字串

OJ题归属:动态规划【区间dp】

解题算法:动态规划

经验总结:区间dp本质可以使用背包那种棋盘式填表顺序,但是由于特判比较多,所以一般使用区间dp特有的填表顺序(第一层:循环子串长度 1 -> n;第二层:循环左端点;右端点可以计算出来)。

此题的五板斧:

cpp 复制代码
#include<iostream>
#include<string>

using namespace std;

const int N = 1010;

string s;
int n;
int f[N][N];

int main()
{
	cin >> s;
	n = s.size();
	s = " " + s;

	for (int len = 1; len <= n; len++)
	{
		for (int left = 1; left + len - 1 <= n; left++)
		{
			int right = left + len - 1;
			if (s[left] == s[right]) f[left][right] = f[left + 1][right - 1];
			else f[left][right] = min(f[left + 1][right], f[left][right - 1]) + 1;
		}
	}

	cout << f[1][n] << endl;

	return 0;
}

OJ题来源:洛谷

OJ题名:Treats for the Cows(款待奶牛)

OJ题归属:动态规划【区间dp】

解题算法:动态规划

经验总结:区间dp本质特点之一:就是只对区间的左右两头端点进行操作。

cpp 复制代码
#include<iostream>

using namespace std;

const int N = 2010;

int n;
int a[N];
int f[N][N];

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];

	for (int len = 1; len <= n; len++)
	{
		for (int i = 1; i + len - 1 <= n; i++)
		{
			int j = i + len - 1;
			f[i][j] = max(f[i + 1][j] + a[i] * (n - len + 1), f[i][j - 1] + a[j] * (n - len + 1));
		}
	}

	cout << f[1][n] << endl;

	return 0;
}

OJ题来源:洛谷

OJ题名:石子合并(弱化版)

OJ题归属:动态规划【区间dp】

解题算法:动态规划 / 小小空间优化的动态规划

五板斧:

cpp 复制代码
#include<iostream>
#include<cstring>

using namespace std;

const int N = 310;

int n;
int a[N];
int sum[N];
int f[N][N];

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		sum[i] = sum[i - 1] + a[i];
	}

	memset(f, 0x3f3f3f3f, sizeof f);
	for (int i = 0; i <= n; i++) f[i][i] = 0;

	for (int len = 2; len <= n; len++)
	{
		for (int i = 1; i + len - 1 <= n; i++)
		{
			int j = i + len - 1;
			int t = sum[j] - sum[i - 1];

			for (int k = i; k < j; k++)
			{
				f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + t);
			}
		}
	}

	cout << f[1][n] << endl;

	return 0;
}

//小小空间优化一下
#include<iostream>
#include<cstring>

using namespace std;

const int N = 310;

int n;
int sum[N];
int f[N][N];

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		int x; cin >> x;
		sum[i] = sum[i - 1] + x;
	}

	memset(f, 0x3f3f3f3f, sizeof f);
	for (int i = 0; i <= n; i++) f[i][i] = 0;

	for (int len = 2; len <= n; len++)
	{
		for (int i = 1; i + len - 1 <= n; i++)
		{
			int j = i + len - 1;
			int t = sum[j] - sum[i - 1];

			for (int k = i; k < j; k++)
			{
				f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + t);
			}
		}
	}

	cout << f[1][n] << endl;

	return 0;
}

OJ题来源:洛谷

OJ题名:石子合并

OJ题归属:动态规划【区间dp】

解题算法:"倍增"/复写 + 动态规划

经验总结:遇到环形的区间dp,可以通过 "倍增"/复写 将环形数据变成直线型数据;比如:环形数据:4、5、9、4 -> 线形数据:4、5、9、4、4、5、9、4。

五板斧:

cpp 复制代码
#include<iostream>
#include<cstring>

using namespace std;

const int N = 210;

int n, m;
int s[N];
int f[N][N]; //min
int g[N][N]; //max

int main()
{
	cin >> n;
	m = 2 * n;
	for (int i = 1; i <= n; i++)
	{
		cin >> s[i];

		// "倍增"/复写
		s[i + n] = s[i];
	}

	//前缀和
	for (int i = 1; i <= m; i++) s[i] = s[i - 1] + s[i];

	//dp
	memset(f, 0x3f3f3f3f, sizeof f);
	memset(g, -0x3f3f3f3f, sizeof g);
	for (int i = 1; i <= m; i++) f[i][i] = g[i][i] = 0;

	for (int len = 1; len <= n; len++)
	{
		for (int i = 1; i + len - 1 <= m; i++)
		{
			int j = i + len - 1;
			int t = s[j] - s[i - 1];
			//枚举分割点
			for (int k = i; k < j; k++)
			{
				f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + t);
				g[i][j] = max(g[i][j], g[i][k] + g[k + 1][j] + t);
			}
		}
	}

	int ret1 = 0x3f3f3f3f, ret2 = -0x3f3f3f3f;
	//枚举 环->线 可能情况的左端点
	for (int i = 1; i <= n; i++)
	{
		ret1 = min(ret1, f[i][i + n - 1]);
		ret2 = max(ret2, g[i][i + n - 1]);
	}

	cout << ret1 << endl << ret2 << endl;

	return 0;
}
相关推荐
2401_894915536 小时前
Geo优化系统源码部署搭建技术——PHP程序开发部署指南
开发语言·php
茯苓gao6 小时前
嵌入式开发笔记:QSerialPort 完整使用指南——从基础 API 到工程实战
笔记·嵌入式硬件·qt·学习
找磁材7 小时前
空心杯电机与永磁体
开发语言·磁性材料·钕铁硼·磁钢
核数聚7 小时前
【赛迪专访核数聚】深耕数据治理,打通数据孤岛夯实 AI 发展根基
大数据·人工智能·算法
我不管我就要叫小猪7 小时前
C/C++----命名空间
c语言·开发语言·c++
小许同学记录成长7 小时前
相对辐射定标技术文档
图像处理·算法
兮动人7 小时前
Python字符串类型
开发语言·python·python字符串类型
自由随风飘7 小时前
JAVA中的面向对象-3
java·开发语言
白白白小纯7 小时前
算法篇—返回倒数第k个节点
c语言·数据结构·算法·leetcode
小羊先生car8 小时前
RTOS-F429-HAL-(动/静态)任务的创建(2026/7/27)
开发语言·算法·c#