NC20242 [SCOI2005]最大子矩阵
题目
题目描述
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。
注意:选出的k个子矩阵 不能相互重叠。
输入描述
第一行为n,m,k(1 ≤ n ≤ 100,1 ≤ m ≤ 2,1 ≤ k ≤ 10),
接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
输出描述
只有一行为k个子矩阵分值之和最大为多少。
示例1
输入
3 2 2
1 -3
2 3
-2 3
输出
9
题解
知识点:线性dp。
发现 \(m=1\) 时,就是 \(k\) 串最大和。
这里解释一下 \(k\) 串最大和的做法,有三种状态设置:取第 \(i\) 个数,共取了 \(j\) 串;考虑到第 \(i\) 个数,共取了 \(j\) 串;考虑到第 \(i\) 个数,共取了 \(j\) 串,第 \(i\) 个数的状态为0/1(不取/取)。
状态转移方程是 \(dp[i][j] = \max(dp[u][j-1],dp[i-1][j]) + a[i],0 \leq u \leq i-1\) ,表示 \(a[i]\) 独立一串和 \(a[i]\) 和前面串起来取最优解,时间复杂度是 \(O(n^2k)\) ,通过前缀最大值优化可以到 \(O(nk)\) 。
状态转移方程是 \(dp[i][j] = \max (dp[u][j-1]+sum[i] - sum[u],dp[i-1][j]), 0 \leq u \leq i-1\) ,表示选 \([u+1 , i]\) 一串和不选优解,时间复杂度是 \(O(n^2k)\)。
状态转移方程是:
\[\begin{aligned}
dp[i][j][0] &= \max (dp[i-1][j][1],dp[i-1][j][0])\\
dp[i][j][1] &= \max(dp[i-1][j][1],dp[i-1][j-1][1],dp[i-1][j-1][0])
\end{aligned}
\]表示不选就在前面的情况取最大值,选就在前面选后串一起或者在前面选后独立成一串或者前面不选独立成串中取最大值。时间复杂度是 \(O(nk)\) 。
要注意的是如果不允许取空串需要赋值负无穷且 \(k=0\) 的初态为 \(0\),如果允许则默认 \(0\) 即可。
现在扩展到 \(m=2\) 。也有三种设置:取第一列的第 \(i\) 个数和第二列的第 \(j\) 个数,共取了 \(u\) 个矩阵;考虑到第一列的第 \(i\) 个数和第二列的第 \(j\) 个数,共取了 \(u\) 个矩阵;考虑到第 \(i\) 行,共取了 \(j\) 个矩阵,第 \(i\) 行状态是 0/1/2/3/4(都不取\取第一列\取第二列\都取但不同块\都取成一块)。
这里写的是第二种,实际上第一种和第二种相似。第三种复杂度是 \(O(nk)\) ,但写起来麻烦,但可用矩阵运算优化写法。
转移方程为:
\left \{
\begin{array}{l}
dp[v][j][k-1]+sum[i][1]-sum[v][1] &,0\leq v\leq i-1\\
dp[i][v][k-1]+sum[j][2]-sum[v][2] &,0\leq v \leq j-1\\
dp[v][v][k-1]+sum[i][1]-sum[v][1]+sum[j][2]-sum[v][2] &,i = j \and 0\leq v \leq i-1\\
dp[i-1][j][k] &,i\geq 1\\
dp[i][j-1][k] &,j\geq 1
\end{array}
\right.
\]
分别指:
- 选第一列 \([v+1,i]\) 作为矩阵。
- 选第二列 \([v+1,j]\) 作为矩阵。
- 在 \(i=j\) 下还能选两列 \([v+1,i]\) 作为矩阵。
- 不选第一列。
- 不选第二列。
这道题数据不太行,其他题解有说可以有空矩阵,我这里写的是包括空矩阵的,但实际上初始化负无穷,\(k=0\) 初态为 \(0\) 做不包含空矩阵的,也是对的。
时间复杂度 \(O(n^2k)\)
空间复杂度 \(O(n^2k)\)
代码
#include <bits/stdc++.h>
using namespace std;
int a[107][10], dp[107][107][17], sum[107][10];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m, k;
cin >> n >> m >> k;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
cin >> a[i][j], sum[i][j] = a[i][j] + sum[i - 1][j];
///不需要从0开始,因为如果从(0,j,k-1)转移到(i,j,k),则有(min(i,j),min(i,j),k-1)到(i,j,k)的转移
///而形如(l,l,k)的状态是可以从 (1,1,1) 开始推的,因此所有都可以从(1,1,1)开始
///感觉好奇怪,还是从(0,0,1)开始舒服
///再者可以选空矩阵,因此不需要初始化负无穷
for (int i = 0;i <= n;i++) {
for (int j = 0;j <= n;j++) {
for (int u = 1;u <= k;u++) {
dp[i][j][u] = max(dp[max(0, i - 1)][j][u], dp[i][max(0, j - 1)][u]);///不选i或j
for (int v = 0;v < i;v++) dp[i][j][u] = max(dp[v][j][u - 1] + sum[i][1] - sum[v][1], dp[i][j][u]);///选i
for (int v = 0;v < j;v++) dp[i][j][u] = max(dp[i][v][u - 1] + sum[j][2] - sum[v][2], dp[i][j][u]);///选j
if (i == j)
for (int v = 0;v < i;v++) dp[i][j][u] = max(dp[v][v][u - 1] + sum[i][1] - sum[v][1] + sum[j][2] - sum[v][2], dp[i][j][u]);///选i和j相连
}
}
}
cout << dp[n][n][k] << '\n';
return 0;
}
NC20242 [SCOI2005]最大子矩阵的更多相关文章
- BZOJ 1084: [SCOI2005]最大子矩阵 DP
1084: [SCOI2005]最大子矩阵 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1084 Description 这里有一个n* ...
- 1084: [SCOI2005]最大子矩阵
1084: [SCOI2005]最大子矩阵 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1325 Solved: 670[Submit][Stat ...
- bzoj千题计划198:bzoj1084: [SCOI2005]最大子矩阵
http://www.lydsy.com/JudgeOnline/problem.php?id=1084 m=1: dp[i][j] 前i个数,选了j个矩阵的最大和 第i个不选:由dp[i-1][j] ...
- 【BZOJ 1084】 1084: [SCOI2005]最大子矩阵 (DP)
1084: [SCOI2005]最大子矩阵 Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. Input 第 ...
- BZOJ(6) 1084: [SCOI2005]最大子矩阵
1084: [SCOI2005]最大子矩阵 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3566 Solved: 1785[Submit][Sta ...
- [Luogu 2331] [SCOI2005]最大子矩阵
[Luogu 2331] [SCOI2005]最大子矩阵 题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 ...
- 洛谷P2331 [SCOI2005]最大子矩阵 DP
P2331 [SCOI2005]最大子矩阵 题意 : 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 第一行为n,m,k(1≤n≤ ...
- [bzoj1084][SCOI2005]最大子矩阵_动态规划_伪·轮廓线dp
最大子矩阵 bzoj-1084 SCOI-2005 题目大意:给定一个n*m的矩阵,请你选出k个互不重叠的子矩阵使得它们的权值和最大. 注释:$1\le n \le 100$,$1\le m\le 2 ...
- [SCOI2005]最大子矩阵
题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2 ...
随机推荐
- 从标准输入流中读取并执行shell指定函数
巧妙的ohmytmux配置 看oh my tmux的配置,发现他们很巧妙的将配置和shell函数放到一个文件里 比如切换鼠标模式的相关配置和shell函数, # : << EOF # .. ...
- Link-Cut-Tree(1)
参考论文 求解范围:(动态树问题) 树上路径查询.修改 动态连边.删边 换根 lca 算法逻辑 概念: 类似树链剖分,把一棵树拆成许多链,每个链用splay维护(链上的为实边,否则为虚边),splay ...
- Spring Security整合企业微信的扫码登录,企微的API震惊到我了
本文代码: https://gitee.com/felord/spring-security-oauth2-tutorial/tree/wwopen/ 现在很多企业都接入了企业微信,作为私域社群工具, ...
- 为什么要写blog????
写 blog 文章,是种与自我的对话,也是种与外界的联系,也是获得 level up 或 skill learned 的契机. 借口:我不太会写文章,不太会表达,没有东西好写,没人会看我的文章 你想让 ...
- jvm造轮子
博客内容来源于 刘欣老师的课程,刘欣老师的公众号 码农翻身 博客内容来源于 Java虚拟机规范(JavaSE7) 博客内容的源码 https://gitee.com/zumengjie/litejvm ...
- 关于Vue 移动端适配 (px2rem 插件将px转为rem)
一.安装 npm install px2rem-loader lib-flexible --save 二.入口文件main.js加上 import 'lib-flexible/flexible.js' ...
- 使用MySqlBulkLoader批量插入数据
最近在项目中遇到插入几万.几十万.几百万的数据到MYSQL数据库,使用EF插入会发现插入速度非常慢的场景, 数据量非常大时EF插入需要几十分钟,甚至几个小时,这样子的速度肯定不是我们所期望的. 后面经 ...
- Mysql安装配置以及解决重装Mysql时忘记root password问题
目录 1.Mysql安装以及环境变量配置 重装Mysql时忘记root password问题 1.Mysql安装以及环境变量配置 官网安装:https://www.mysql.com/ 按 ...
- CMU15445 (Fall 2019) 之 Project#3 - Query Execution 详解
前言 经过前面两个实验的铺垫,终于到了给数据库系统添加执行查询计划功能的时候了.给定一条 SQL 语句,我们可以将其中的操作符组织为一棵树,树中的每一个父节点都能从子节点获取 tuple 并处理成操作 ...
- Python进程管理神器——Supervisor
一.简介 Supervisor 是一款 Python 开发的进程管理系统,允许用户监视和控制 Linux 上的进程,能将一个普通命令行进程变为后台守护进程,异常退出时能自动重启 详细介绍查阅:Supe ...