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;
}
相关推荐
小灰灰搞电子10 小时前
Rust+Slint 实现动态消息提示框源码分享
开发语言·后端·rust
李帅朋10 小时前
微分基本定义笔记
人工智能·笔记·深度学习·神经网络
神仙别闹11 小时前
基于 C++ 实现两个有序链表序列的交集
java·c++·链表
传奇开心果编程11 小时前
【Rust入门知识点学与练】第21课:Trait 进阶 Advanced Traits
开发语言·学习·rust
新时代牛马12 小时前
字符设备驱动完整篇:从 cdev_add、file_operations 到chrdev_open 与排障
开发语言·python
swordbob12 小时前
ReentrantLock 与 AQS 完整学习手册
java·开发语言
政企项目老覃12 小时前
大模型幻觉治理与自动评测:金融风控场景的落地实践
人工智能·算法·机器学习
淡海水12 小时前
08-03-不可变-ImmutableDictionary-TKey-TValue-与ImmutableHashSet-T-持久化哈希树
数据结构·算法·c#·哈希算法·dictionary·immutable
白山编程大哥12 小时前
Java OutputStreamWriter 详解:从字符到字节的桥梁
java·开发语言·python