《算法竞赛进阶指南》0x53 区间DP

news/2024/11/28 1:17:18/

0x53 区间DP

石子合并

题意:

合并两堆相邻石子的代价为两堆石子的质量和。将所有堆石子合并为 1 堆的最小代价。

解析:

长的区间一定由短区间转移,所以按区间长度划分阶段。枚举长区间的分割点进行转移

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 3e2+10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;int n;
int f[maxn][maxn];
int a[maxn], sum[maxn];int main(){ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);cin >> n;for(int i = 1; i <= n; i++){cin >> a[i];sum[i] = sum[i-1] + a[i];}memset(f, INF, sizeof(f));for(int i = 1; i <= n; i++)f[i][i] = 0;for(int len = 2; len <= n; len++){for(int st = 1; st <= n-len+1; st++){int ed = len+st-1;for(int k = st; k < ed; k++){f[st][ed] = min(f[st][ed], f[st][k]+f[k+1][ed]+sum[ed]-sum[st-1]);}}}cout << f[1][n];return 0;
}

多边形

题意:

一个多边形,边上是运算符 *+,点上是数字。每次操作可以去掉一条边和两个顶点,产生一个新点,新点上的数字为删除的运算结果。

只剩一个点时,最大的数字。

解析:

先断环成链。因为数字可以为负,最大值不一定由最大值转移而来,但一定由最值转移。

所以令 fk=0/1,i,jf_{k=0/1,i,j}fk=0/1,i,j 为区间 [i,j][i,j][i,j] 合并成一个点的最值。k=0k=0k=0 为最大值,k=1k=1k=1 为最小值。

然后同上题,枚举分割点进行转移。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 100+10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;int a[maxn], n;
int dp[2][maxn][maxn];
char op[maxn];
int cal(int a, int b, char ch){if(ch == 'x')return a * b;elsereturn a + b;
}
int main(){ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);cin >> n;for(int i = 1; i <= n; i++){cin >> op[i] >> a[i];op[n+i] = op[i]; a[i+n] = a[i];}memset(dp[0], -INF, sizeof(dp[0]));memset(dp[1], INF, sizeof(dp[1]));for(int i = 1; i <= n * 2; i++)dp[0][i][i] = dp[1][i][i] = a[i];for(int len = 2; len <= n; len++){for(int st = 1; st <= 2*n-len+1; st++){int ed = st+len-1;for(int k = st; k < ed; k++){for(int i = 0; i <= 1; i++){for(int j = 0; j <= 1; j++){dp[0][st][ed] = max(dp[0][st][ed], cal(dp[i][st][k], dp[j][k+1][ed], op[k+1]));dp[1][st][ed] = min(dp[1][st][ed], cal(dp[i][st][k], dp[j][k+1][ed], op[k+1]));}}}}}	vector<int> res;int maxx = -INF;for(int i = 1; i <= n; i++){int t = dp[0][i][i+n-1];if(t > maxx){res.clear();maxx = t;res.push_back(i);}else if(maxx == t)res.push_back(i);}cout << maxx << endl;for(auto x : res)cout << x << " ";return 0;
}


金字塔

题意:

一个树,每个点有一个颜色。按照dfs遍历这棵树会产生一个颜色序列。每到一个节点(无论是第一次进入还是返回),都会记录这个节点的颜色。除叶子节点,其余节点至少访问两次。

给定一个颜色序列,询问有多少种树的结构能产生这个序列。

解析:

区间DP+记忆化搜索

对以 uuu 为节点的子树,产生的序列形如:u−subtree1−u−subtree2−...−subtreex−uu-subtree_1-u-subtree_2-...-subtree_x-uusubtree1usubtree2...subtreexuxxxuuu 的儿子个数。

可以将这棵树分为两部分:u−subtree1u-subtree_1usubtree1u−subtree2−...−subtreex−uu-subtree_2-...-subtree_x-uusubtree2...subtreexu。设第二部分的起点位置为 kkk,则 dpl,r+=dpl,k−1×dpk,rdp_{l,r} += dp_{l,k-1}\times dp_{k,r}dpl,r+=dpl,k1×dpk,r

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 3e2+10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9;
typedef pair<int, int> pii;ll dp[maxn][maxn];
char s[maxn];
ll dfs(int l, int r){if(l > r)return 0;else if(l == r)return 1;if(dp[l][r] != -1)return dp[l][r];ll &res = dp[l][r];res = 0;if(s[l] == s[r]){for(int k = l; k <= r; k++){res = (res + dfs(l+1, k-1) * dfs(k, r)) % mod;}}return res;
}int main(){ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);cin >> s+1;memset(dp, -1, sizeof(dp));cout << dfs(1, strlen(s+1));return 0;
}

http://www.ppmy.cn/news/40197.html

相关文章

【redis】集群

redis集群 集群有点难 大部分的实操命令没有记录 希望能二刷补上 18:46 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录redis集群前言一、集群是什么&#xff1f;二、集群能干嘛&#xff1f;三、集群算法-分片-槽…

xor(vector+字典树)

题目大意 给出一个长度为nnn的序列AAA&#xff0c;再给出一个整数xxx&#xff0c;如果一个子序列满足以下的条件&#xff0c;则它是一个符合条件的子序列&#xff1a; 序列中的任意两个数的异或结果都大于等于xxx 求符合条件的子序列的个数&#xff0c;模998244353998244353…

针对近日ChatGPT账号大批量封禁的理性分析

文 / 高扬 这两天不太平。 3月31号&#xff0c;不少技术圈的朋友和我闲聊说&#xff0c;ChatGPT账号不能注册了。 我不以为然&#xff0c;自己有一个号足够了&#xff0c;并不关注账号注册的事情。 后面又有不少朋友和我说ChatGPT账号全部不能注册了&#xff0c;因为老美要封锁…

Winform控件开发(30)——MonthCalendar(史上最全)

前言 MonthCalendar控件用于显示日期,也就是某年某月某日 一、属性 1、Name 用户获取控件对象 2、AllowDrop 指示是否允许用户拖动数据到控件上 3、Anchor 设置控件相对于父控件锚定的位置 4、AnnuallyBoldedDates 设置每一年的该日期是否加粗显示,该属性的值是一个…

【kubernetes-工具篇】K9S详解-宝藏k8s界面工具

K9S简介 K9s是一个命令行界面&#xff08;CLI&#xff09;工具&#xff0c;用于管理Kubernetes集群。它是一个流行的开源工具&#xff0c;可以帮助Kubernetes管理员和开发人员轻松管理他们的Kubernetes集群。在本文中&#xff0c;我们将简单介绍K9s的概念、功能和如何使用它。…

Oracle的学习心得和知识总结(十八)|Oracle数据库性能压测工具swingbench的安装和使用及AWR ASH ADDM报告生成

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《Oracle Database SQL Language Reference》 2、参考书籍&#xff1a;《PostgreSQL中文手册》 3、EDB Postgres Advanced Server User Guid…

【Kubernetes 企业项目实战】11、掌握 Kubernetes Kustomize 技术从入门到企业实战(下)

目录 一、Kustomize 进阶 1.1 使用覆盖定制资源 1.1.1 kustomization.yaml 1.1.2 deploy-patch.yaml 1.1.3 ing-patch.yaml 1.1.4 op 操作类型介绍 二、生成测试环境定制资源 三、使用 Kustomize 来应用、查看和删除对象 3.1 创建应用 3.2 查看应用 3.3 删除应用 四…