BZOJ1084或洛谷2331 [SCOI2005]最大子矩阵
BZOJ原题链接
洛谷原题链接
注意该题的子矩阵可以是空矩阵,即可以不选,答案的下界为\(0\)。
设\(f[i][j][k]\)表示前\(i\)行选择了\(j\)个子矩阵,选择的方式为\(k\)时的最大分值之和。
- \(k = 0\)表示该行不选数。
- \(k = 1\)表示该行只选左边的数。
- \(k = 2\)表示该行只选右边的数。
- \(k = 3\)表示该行选两个数,但分别属于两个子矩阵。
- \(k = 4\)表示该行选两个数,属于一个子矩阵。
设一行中左边的数为\(x\),右边的数为\(y\)。
- \(k = 0\)时
直接由上一层转移来:$$f[i][j][0] = \max{ f[i][j][0], f[i - 1][j][0], f[i - 1][j][1], f[i - 1][j][2], f[i - 1][j][3], f[i - 1][j][4] }$$
- \(k = 1\)时
若上层状态为\(1\)或\(3\),则可以直接接上去,其它的都需要另开一个子矩阵:$$f[i][j][1] = \max{ f[i][j][1], \max{ f[i - 1][j - 1][0], f[i - 1][j][1], f[i - 1][j - 1][2], f[i - 1][j][3], f[i - 1][j - 1][4] } + x}$$
- \(k = 2\)时
若上层状态为\(2\)或\(3\),则可以直接接上去,其它的都需要另开一个子矩阵:$$f[i][j][2] = \max{ f[i][j][2], \max{ f[i - 1][j - 1][0], f[i - 1][j - 1][1], f[i - 1][j][2], f[i - 1][j][3], f[i - 1][j - 1][4] } + y}$$
- \(k = 3\)时
若上层状态为\(3\),则可以直接接上去,若为\(0\)或\(4\),则需要另开两个子矩阵,其它的都需要另开一个子矩阵:$$f[i][j][3] = \max{ f[i][j][3], \max{ f[i - 1][j - 2][0], f[i - 1][j - 1][1], f[i - 1][j - 1][2], f[i - 1][j][3], f[i - 1][j - 2][4] } + x + y }$$
- \(k = 4\)时
若上层状态为\(4\),则可以直接接上去,其它的都需要另开一个子矩阵:$$f[i][j][4] = \max{ f[i][j][4], \max{ f[i - 1][j - 1][1], f[i - 1][j - 1][2], f[i - 1][j - 1][3], f[i - 1][j][4] } + x + y }$$
\(f\)直接初始化全为\(0\),因为可以取空矩阵,即不选数。
最后答案为\(\max\{ f[n][k][0], f[n][k][1], f[n][k][2], f[n][k][3], f[n][k][4] \}\)。
在\(DP\)过程中注意判断边界,部分状态对宽度或是子矩阵个数有要求。
因为没开循环,所以代码及其难看。。
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 110;
int f[N][12][5], a[N][N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline int maxn(int x, int y)
{
return x > y ? x : y;
}
inline void ckmaxn(int &x, int y)
{
if (x < y)
x = y;
}
int main()
{
int i, j, n, m, k;
n = re();
m = re();
k = re();
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
a[i][j] = re();
for (i = 1; i <= n; i++)
for (j = 1; j <= k; j++)
{
ckmaxn(f[i][j][0], maxn(f[i - 1][j][0], f[i - 1][j][1]));
ckmaxn(f[i][j][1], maxn(f[i - 1][j - 1][0], f[i - 1][j][1]) + a[i][1]);
if (m > 1)
{
ckmaxn(f[i][j][0], maxn(f[i - 1][j][2], f[i - 1][j][4]));
ckmaxn(f[i][j][1], maxn(f[i - 1][j - 1][2], f[i - 1][j - 1][4]) + a[i][1]);
ckmaxn(f[i][j][2], maxn(maxn(f[i - 1][j - 1][0], f[i - 1][j - 1][1]), maxn(f[i - 1][j][2], f[i - 1][j - 1][4])) + a[i][2]);
ckmaxn(f[i][j][4], maxn(maxn(f[i - 1][j - 1][0], f[i - 1][j - 1][1]), maxn(f[i - 1][j - 1][2], f[i - 1][j][4])) + a[i][1] + a[i][2]);
if (j > 1)
{
ckmaxn(f[i][j][0], f[i - 1][j][3]);
ckmaxn(f[i][j][1], f[i - 1][j][3] + a[i][1]);
ckmaxn(f[i][j][2], f[i - 1][j][3] + a[i][2]);
ckmaxn(f[i][j][3], maxn(maxn(f[i - 1][j - 2][0], maxn(f[i - 1][j - 1][1], maxn(f[i - 1][j - 1][2], f[i - 1][j][3]))), f[i - 1][j - 2][4]) + a[i][1] + a[i][2]);
ckmaxn(f[i][j][4], f[i - 1][j - 1][3] + a[i][1] + a[i][2]);
}
}
}
printf("%d", maxn(maxn(f[n][k][0], f[n][k][1]), maxn(f[n][k][2], maxn(f[n][k][3], f[n][k][4]))));
return 0;
}
BZOJ1084或洛谷2331 [SCOI2005]最大子矩阵的更多相关文章
- bzoj1084&&洛谷2331[SCOI2005]最大子矩阵
题解: 分类讨论 当m=1的时候,很简单的dp,这里就不再复述了 当m=2的时候,设dp[i][j][k]表示有k个子矩阵,第一列有i个,第二列有j个 然后枚举一下当前子矩阵,状态转移 代码: #in ...
- 洛谷 P2331 [SCOI2005]最大子矩阵
洛谷 这一题,乍一眼看上去只想到了最暴力的暴力--大概\(n^4\)吧. 仔细看看数据范围,发现\(1 \leq m \leq 2\),这就好办了,分两类讨论. 我先打了\(m=1\)的情况,拿了30 ...
- 洛谷P2331 [SCOI2005]最大子矩阵 DP
P2331 [SCOI2005]最大子矩阵 题意 : 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 第一行为n,m,k(1≤n≤ ...
- 洛谷P2331 [SCOI2005] 最大子矩阵[序列DP]
题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2 ...
- 洛谷P2331[SCOI2005]最大子矩阵
题目 DP 此题可以分为两个子问题. \(m\)等于\(1\): 原题目转化为求一行数列里的\(k\)块区间的和,区间可以为空的值. 直接定义状态\(dp[i][t]\)表示前i个数分为t块的最大值. ...
- 洛谷 P1896 [SCOI2005]互不侵犯
洛谷 P1896 [SCOI2005]互不侵犯 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8 ...
- [Luogu 2331] [SCOI2005]最大子矩阵
[Luogu 2331] [SCOI2005]最大子矩阵 题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 ...
- BZOJ1088或洛谷2327 [SCOI2005]扫雷
BZOJ原题链接 洛谷原题链接 很容易发现答案就只有\(0,1,2\)三种答案,而且只要知道第一个格子是否有雷就可以直接顺推下去了. 所以我们跑一次首位有雷,跑一次首位无雷判断是否可行即可. #inc ...
- 【题解】洛谷P1896 [SCOI2005] 互不侵犯(状压DP)
洛谷P1896:https://www.luogu.org/problemnew/show/P1896 前言 这是一道状压DP的经典题 原来已经做过了 但是快要NOIP 复习一波 关于一些位运算的知识 ...
随机推荐
- Spring @ControllerAdvice @ExceptionHandler 全局处理异常
对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚. 如此一来, ...
- 1.3、CDH 搭建Hadoop在安装之前(端口)
端口 Cloudera Manager,CDH组件,托管服务和第三方组件使用下表中列出的端口.在部署Cloudera Manager,CDH和托管服务以及第三方组件之前,请确保在每个系统上打开这些端口 ...
- webservice客户端 get delete post 请求
package com.cn.eport.util.common; import java.io.IOException; import java.util.List; import org.apac ...
- 外购半成品报SHORT问题(非验货客户)
外购半成品报SHORT问题(验货客户)https://www.cnblogs.com/Snowfun/p/8660646.html 下面看非验货客户: 1.检查采购类型是否为F(SAP_MARC),为 ...
- The <classpath> or <modulepath> for <junit> must include junit.jar if not in Ant's own classpath
The <classpath> or <modulepath> for <junit> must include junit.jar if not in Ant's ...
- day12 装饰器的模版
1.什么是装饰器 装饰器指的是为被装饰对象(别人)添加新功能的工具 装饰器本身可以是任意可调用对象 被装饰器对象也可以是任意可调用对象 2.为何要用装饰器 开放封闭原则:指的是对修改封闭,对扩展开放 ...
- zabbix_server.conf 详解
# This is a configuration file for Zabbix server daemon # To get more information about Zabbix, visi ...
- vue项目打包后图片路径问题
当用vue-cli自动构建项目后,有两种运行方法,分别是: npm run dev : 提供一个开发的环境,自动热更新,资源使用绝对路径,所以可以正常看到背景图片. npm run build : 打 ...
- 全国绿色计算大赛 模拟赛第一阶段(C++)第1关:求和
挑战任务 这次“绿盟杯”大赛,小明作为参赛选手在练习的时候遇到一个问题,他要对一个范围的两个数进行数位的累加,例如有两个数 15,19 则 他们的数位和应该为:1+5+1+6+1+7+1+8+1+9, ...
- mysql中创建event定时任务
从网上借鉴大神的. use onlinexam; -- 查看event事件是否开启 show variables like '%sche%'; -- 开启event事件 (非常重要) set glo ...