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;
}
相关推荐
梦里寻码23 分钟前
我用 NestJS + Vue3 写了一套完整的研发管理系统(58 表 / 229 API / 130 项断言,全开源
前端·后端·算法
FRing0325 分钟前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
旖旎夜光27 分钟前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习
猿人谷1 小时前
Surrogate Model:让进化算法学会“预测”,为什么它正在成为智能优化的重要技术?
后端·算法·架构
starzy19901 小时前
深入理解Scala嵌套函数:作用域封装之道
开发语言·scala
Sakura_j_h_1 小时前
从零写一个 MCP stdio Server:用 Python 校验博客文章格式
开发语言·python·自动化·ai工具·mcp·json-rpc
Oll Correct2 小时前
Adobe illustrator 案例十二:视频播放(Media & Video)图标绘制
笔记·ui·adobe·illustrator
青少儿编程课堂2 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
白杨尚青3 小时前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树