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 复习一波 关于一些位运算的知识 ...
随机推荐
- NFS 网络文件系统制作
1. 构建根文件系统主要是建立相关的文件目录,以及各目录下相关的配置文件.管理工具等. 2. 首先创建文件目录. mkdir rootfs cd rootfs mkdir bin dev etc li ...
- 构建缓存gradle
结合Kotlin使用Gradle build cache 宛丘之上兮 关注 2018.03.11 00:21* 字数 1177 阅读 505评论 5喜欢 4 在2017年4月,Gradle发布了bui ...
- Eclipse里的代码光标变成一个黑色块
以前经常在编写程序是不知到碰到键盘上的那个键了,或是那几个组合键了,使得Eclipse里的代码光标变成一个黑色块:在这个状态下,光标不在活动自如,只能一直往后写代码,就不想平时的 " | & ...
- Java中的IO流(一)
一,IO流的分类 A,按照操作的对象不同可分为字节流与字符流 B,按照流的方向不同可分为输入(指从外部存储设备拿文件到内存)流也叫读与输出(指从内存把文件写入到外部存储设备)流也叫写 注:字节流可以操 ...
- 03_java基础(五)之项目结构搭建
1.结构图 2.dao代码编辑 package com.day01.station.dao; /** * Created by Administrator on 2018/2/1. */ public ...
- java中map接口hashMap以及Enty之间的用法和关系
java中map接口hashMap以及Enty之间的转换 首先说的是map接口: Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value ...
- Real Time Render 4
[Real Time Render 4] 1.Radiometry(辐射测试) deals with the measurement of electromagnetic(电磁) radiation( ...
- native和webview切换
native和webview 标签(空格分隔): native和webview 现在目前大部分的app都是native和webview混合,对应的native上的元素可以通过uiautomatorvi ...
- Monkey 命令收集相关 --追加Monkey自动化测试开源工具
.1.环境配置 MONKEY测试使用的是ADB命令,因此只需要配置ADB环境即可. 2.测试准备与执行 在Monkey测试前,必须进行以下准备 Ø 手机屏幕超时设置为30分钟或者永不超时,防止手机进 ...
- POJ-3279.Fliptile(二进制状态压缩 + dfs) 子集生成
昨天晚上12点刷到的这个题,一开始一位是BFS,但是一直没有思路.后来推了一下发现只需要依次枚举第一行的所有翻转状态然后再对每个情况的其它田地翻转进行暴力dfs就可以,但是由于二进制压缩学的不是很透, ...