BZOJ1084 [SCOI2005]最大子矩阵 动态规划
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1084
题意概括
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。
输入:第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
题解
注意到1<=m<=2!
如果m = 1 ,那么就是一个简单的线性dp。
我们设dp[i][j]表示在前i个里面选出k个子矩阵的最大分值。
那么分两种情况讨论:
1. 什么都不干: dp[i][j] = max(dp[i][j], dp[i-1][j])
2. 弄一个新的子矩阵: dp[i][j] = max(dp[i][j], dp[x][j - 1] + presum[i] - presum[x]) 0<=x<i
时间复杂度O(kn2)
如果 m = 2 ,那么是一个稍微复杂一点的线性dp。
我们设dp[i][j][x]表示在第一列的前i个和第二列的前j个里面选出x个子矩阵的最大分值。
那么分几种情况进行讨论:
1. 什么都不干: dp[i][j][x] = max(dp[i][j][x], dp[i - 1][j][x], dp[i][j - 1][x])
2. 在第一列弄一个新的子矩阵: dp[i][j][x] = max(dp[i][j][x], dp[y][j][x - 1] + presum[i][1] - presum[y][1]) 0<=y<i
3. 在第二列弄一个新的子矩阵: dp[i][j][x] = max(dp[i][j][x], dp[i][y][x - 1] + presum[j][2] - presum[y][2]) 0<=y<j
4. 在第一、二列弄一个宽度为2的子矩阵: dp[i][j][x] = max(dp[i][j][x], dp[y][y][x - 1] + presum[i][1] - presum[y][1] + presum[j][2] - presum[y][2]) i = j 且 0<=y<i
时间复杂度O(kn3)
代码
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=+,M=,K=+;
const int Inf=<<;
int n,m,k,a[N][M];
void solve1(){
int dp[N][K],presum[N];
for (int i=;i<N;i++)
for (int j=;j<K;j++)
dp[i][j]=-Inf;
presum[]=;
for (int i=;i<=n;i++)
presum[i]=presum[i-]+a[i][];
dp[][]=;
int ans=-Inf;
for (int i=;i<=n;i++)
for (int j=;j<=k;j++){
if (!i&&!j)
continue;
if (i)
dp[i][j]=dp[i-][j];
if (!j)
continue;
for (int x=;x<i;x++)
dp[i][j]=max(dp[i][j],dp[x][j-]+presum[i]-presum[x]);
}
printf("%d",dp[n][k]);
}
void solve2(){
int dp[N][N][K],presum[N][M];
presum[][]=presum[][]=;
for (int i=;i<=n;i++){
presum[i][]=presum[i-][]+a[i][];
presum[i][]=presum[i-][]+a[i][];
}
for (int i=;i<N;i++)
for (int j=;j<N;j++)
for (int x=;x<K;x++)
dp[i][j][x]=-Inf;
dp[][][]=;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
for (int x=;x<=k;x++){
if (!i&&!j&&!x)
continue;
if (i&&j)
dp[i][j][x]=max(dp[i-][j][x],dp[i][j-][x]);
else if (i)
dp[i][j][x]=dp[i-][j][x];
else if (j)
dp[i][j][x]=dp[i][j-][x];
if (!x)
continue;
for (int y=;y<i;y++)
dp[i][j][x]=max(dp[i][j][x],dp[y][j][x-]+presum[i][]-presum[y][]);
for (int y=;y<j;y++)
dp[i][j][x]=max(dp[i][j][x],dp[i][y][x-]+presum[j][]-presum[y][]);
if (i==j)
for (int y=;y<i;y++)
dp[i][j][x]=max(dp[i][j][x],dp[y][y][x-]+presum[i][]-presum[y][]+presum[j][]-presum[y][]);
}
printf("%d",dp[n][n][k]);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
scanf("%d",&a[i][j]);
if (m==)
solve1();
else
solve2();
return ;
}
BZOJ1084 [SCOI2005]最大子矩阵 动态规划的更多相关文章
- [bzoj1084][SCOI2005]最大子矩阵_动态规划_伪·轮廓线dp
最大子矩阵 bzoj-1084 SCOI-2005 题目大意:给定一个n*m的矩阵,请你选出k个互不重叠的子矩阵使得它们的权值和最大. 注释:$1\le n \le 100$,$1\le m\le 2 ...
- 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] ...
- bzoj1084: [SCOI2005]最大子矩阵 dp
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 题解:m很小分类讨论,m==1时怎么搞都可以,m==2时,dp[i][j][k]表 ...
- BZOJ 1084 [SCOI2005]最大子矩阵 - 动态规划
传送门 题目大意: 从矩阵中取出k个互不重叠的子矩阵,求最大的和. 题目分析: 对于m=1,直接最大m子段和. 对于m=2: \(dp[i][j][k]\)表示扫描到第一列i和第2列j时选取了k个矩阵 ...
- bzoj1084: [SCOI2005]最大子矩阵
dp.状态转移方程在代码里 #include<cstdio> #include<algorithm> #include<cstring> using namespa ...
- BZOJ1084 SCOI2005最大子矩阵
考虑DP f[i][j][k]表示一行到i一行到j共取k块最大值,类似于最长公共子序列n^2那种 注意相等时可以一起拿 By:大奕哥 #include<bits/stdc++.h> usi ...
- [SCOI2005]最大子矩阵 (动态规划)
题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2 ...
- bzoj1084 [SCOI2005]最大子矩阵——背包
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1084 水题...分类讨论一下即可. 代码如下: #include<iostream&g ...
- [bzoj1084][SCOI2005]最大子矩阵(DP)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1084 分析: m=1时:相当于只有一行数,让你取出p段,使得总和最大 明显可以DP,f ...
随机推荐
- 作业引擎quartz.net --- 监听链
针对多个作业:如何描述各个跑批任务之间的顺序,紧前.紧后关系,实现灵活调度.例如:A完成则B开始,B完成C开始. 对quartz.net 进行了查阅,能实现如上业务,如下图: 测试代码: using ...
- Aircrack-ng介绍
1.介绍 Aircrack-ng主要使用了两种攻击方式进行WEP破解:一种是FMS攻击:一种是KoreK攻击. 2.主要组件 1.aircrack-ng 主要用于WEP及WPA-PSK密码的恢复,主要 ...
- AAA游戏中雪的实现
现在越来越多的AAA游戏中都实现了逼真的雪的效果,比如战神4.地平线:黎明时分.荒野大镖客:救赎2.古墓丽影:崛起等都实现了不错的雪地效果.今天我们就来探究一下他们的实现方式.现在主流的实现方式都是通 ...
- CF875D High Cry
传送门 题目要求合法的区间个数,这里考虑用总区间个数减去不合法的个数 假设某个数为区间最大值,那么包含这个数的最长区间内,所有数小于他并且所有数没有这个最大值没有的二进制位,可以按位考虑每个数\(i\ ...
- Python字符串解析方法汇总
Python字符串方法解析 1.capitalize 将首字母大写,其余的变成小写 print('text'.capitalize()) print('tExt'.capitalize()) 结果: ...
- Delphi基础必记-快捷键
快捷键: F12 代码窗口/窗体之间切换Ctrl + Shift + F 查找文件 Ctrl + Shift + G 为接口加入新的GUIDF4 运行到光标位置 F5 设置/取消断点 或用光标点击F7 ...
- 关于django1.7.7使用ajax后出现“CSRF token missing or incorrect”问题的解决办法
最近使用Python3.3.25和django1.7.7开发公司项目,在使用ajax来post数据时,居然一直提示:403错误,原因是“CSRF token missing or incorrect” ...
- 算法时间复杂度和NP问题简介
这里主要简单说一下算法的时间复杂度和NP问题简介,毕竟分析算法的时间复杂度上界有助于分析算法的好坏,分析算法好坏也有助于分析是否还有更好的算法: 一.时间复杂度: 一般关心的还有递归问题中的时间复杂度 ...
- 【Shell】带颜色输出(白底x色)
echo -e "\033[31mHello World.\033[0m" 红色31m 绿色32m 黄色33m 蓝色34m 黑色30m 白色37m 紫色35m 深绿色36m
- 用python查看windows事件日志的方法(待后续研究)
#coding=utf8 import copy import ctypes from ctypes import byref, POINTER, cast, c_uint64, c_ulong, c ...