题目描述

有一个n*m的矩阵,恰好改变其中一个数变成给定的常数P,使得改变后的这个矩阵的最大子矩阵最大。

数据范围

n,m<=300。

题解:

   ①如果没有p,那么二维矩阵和就是一维最长连续子序列的DP升级就可以了:

     设f[i][j][k]表示在i行j行之间1~k列这一个矩形中的最大子矩阵的值

     转移方程:f[i][j][k]=max(f[i][j][k-1]+sum[k],sum[k])

     其中sum[k]表示(i,k)-(j,k)这一段一维序列的元素和。

     上述在代码实现的时候可以压维,即覆盖以前的答案。

     

   ②根据题意,加一维[1/0]表示到目前为止最优矩阵中有没有点被更改了:
       然后转移同理,只是如果选择修改,肯定是修改最小的数,所以使用RMQ或者暴力得出即可

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
const double eps = 1e-6;
const double Pi = acos(-1.0);
const int INF=0x3f3f3f3f; const int maxn = 310;
int mat[maxn][maxn];
int minval[maxn];
int sum[maxn];
int dp[maxn][2]; int dp1(int* sum,int m,int p){
int ret = -INF;
for(int i = 0; i < m; i++){
int minn = INF;
int summ = 0;
for(int j = i; j < m; j++){
summ += sum[j];
minn = min(minn,minval[j]);
if(i == 0 && j == m-1){
ret = max(ret,summ - minn + p);
}else{
int maxx = max(summ,summ - minn + p);
ret = max(maxx,ret);
}
}
}
return ret; } int dp2(int* sum,int m,int p){
dp[0][0] = sum[0];
dp[0][1] = sum[0] - minval[0] +p;
for(int i = 1; i < m; i++){
dp[i][0] = max(dp[i-1][0],0)+sum[i];
dp[i][1] = max(dp[i-1][1] + sum[i],max(dp[i-1][0],0) + sum[i] - minval[i] + p);
}
int ret = -INF;
for(int i = 0; i < m; i++){
ret = max(ret,max(dp[i][0],dp[i][1]));
}
return ret;
} int solve(int n,int m,int p){
int ans = -INF;
for(int i = 0; i < n; i++){
fill(sum,sum+m+1,0);
fill(minval,minval+m+1,INF);
for(int j = i; j < n; j++){
for(int k = 0; k < m; k++){
sum[k] += mat[j][k];
minval[k] = min(minval[k],mat[j][k]);
}
if(i == 0 && j == n-1){
ans = max(ans,dp1(sum,m,p));
}else{
ans = max(ans,dp2(sum,m,p));
}
}
}
return ans;
} int main(){
int n,m,p;
while(~scanf("%d%d%d",&n,&m,&p)){
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
scanf("%d",&mat[i][j]);
}
}
printf("%d\n",solve(n,m,p));
}
return 0;
}//czy020202

我只想朝着远方边走边唱,歌唱这生命美丽和迷惘。————汪峰《边走边唱》

【CZY选讲·最大子矩阵和】的更多相关文章

  1. 【CZY选讲·Hja的棋盘】

    题目描述 Hja特别有钱,他买了一个×的棋盘,然后Yjq到这个棋盘来搞事.一开始所有格子都是白的,Yjq进行次行操作次列操作,所谓一次操作,是将对应的行列上的所有格子颜色取反.现在Yjq希望搞事之后 ...

  2. 【CZY选讲·吃东西】

    题目描述 一个神秘的村庄里有4家美食店.这四家店分别有A,B,C,D种不同的美食.LYK想在每一家店都吃其中一种美食.每种美食需要吃的时间可能是不一样的.现在给定第1家店A种不同的美食所需要吃的时间 ...

  3. 【CZY选讲·一道图论神题】

    题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只有点权. LYK想把这个图删干净,它的方法是这样的.每次选择一个点,将它删掉,但删这个点是需要代价的 ...

  4. 【CZY选讲·Yjq的棺材】

    题目描述 Yjq想要将一个长为宽为的矩形棺材(棺材表面绝对光滑,所以棺材可以任意的滑动)拖过一个L型墓道. 如图所示,L型墓道两个走廊的宽度分别是和,呈90°,并且走廊的长度远大于. 现在Hja ...

  5. 【CZY选讲·逆序对】

    题目描述 LYK最近在研究逆序对. 这个问题是这样的. 一开始LYK有一个2^n长度的数组ai. LYK有Q次操作,每次操作都有一个参数k.表示每连续2^k长度作为一个小组.假设 n=4,k= ...

  6. 【CZY选讲·Triangle】

    题目描述 长度为的铁丝,你可以将其分成若干段,并把每段都折成一个三角形.你还需要保证三角形的边长都是正整数并且三角形两两相似,问有多少种不同的分法. 数据范围 1≤≤10^6 题解:      ①相 ...

  7. 【CZY选讲·棋盘迷宫】

    题目描述 一个N*M的棋盘,’.’表示可以通过,’#’表示不能通过,给出Q个询问,给定起点和终点,判断两点是否联通,如联通输出“Yes”,否则输出“No”. 数据范围 N,M <=500,Q ...

  8. 【CZY选讲·扩展LCS】

    题目描述 给出两个仅有小写字母组成的字符串str1 和str2,试求出两个串的最长公共子序列. 数据范围 |str1| ⩽ 1000; |str2| ⩽ 10^6 题解:    ①直接进行LCS( ...

  9. 【CZY选讲·次大公因数】

    题目描述 给定n个数ai,求sgcd(a1,a1),sgcd(a1,a2),…,sgcd(a1,an). 其中sgcd(x,y)表示x和y的次大公因数.若不存在次大公因数,sgcd(x,y)=-1 ...

随机推荐

  1. ABAP调用WebService时日期类型问题

    在使用ABAP调用WebService时, 提示CX_SY_CONVERSION_NO_DATE_TIME,意思是日期格式不能转化. 究其原因是ABAP里没有相应的数据类型与WebService描述里 ...

  2. 基于WSAAsyncSelect模型的两台计算机之间的通信

    任务目标 编写Win32程序模拟实现基于WSAAsyncSelect模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递.客户端向服务器端发送"请输出从1到1000内所有 ...

  3. c# 解决读取Excel混合文本类型,数据读取失败的解决方法

    错误重现: ----------------------------------------------------------------------- 在导入Excel读取数据时,其中的一个字段保 ...

  4. Linux中的代码编辑器vim

    Vim的三种工作模式 命令行模式 插入模式 底行模式 Vim 的命令行模式 命令行模式是进入vim后的初始模式,在该模式下主要是使用方向键来移动光标的位置,并通过相应的命令来进行文字的编辑. 切换方法 ...

  5. yii2邮箱发送

    yii2 邮件发送  163邮箱 1.在配置文件main-local.php components=>[]里面配置 'mailer' => [ 'class' => 'yii\swi ...

  6. python -- 输出异常详细信息

    在使用try:  except:  捕获异常后,想要获取到异常信息的详细内容另做它用,可以使用python的内置模块traceback进行获取. traceback.print_exc() 直接打印异 ...

  7. Pythony的数据类型和变量使用方法详解

    数据类型:计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定 ...

  8. 数据结构学习-AVL平衡树

    环境:C++ 11 + win10 IDE:Clion 2018.3 AVL平衡树是在BST二叉查找树的基础上添加了平衡机制. 我们把平衡的BST认为是任一节点的左子树和右子树的高度差为-1,0,1中 ...

  9. source tree 使用心得

    SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端管理工具,同时也是Mercurial和Subversion版本控制系统工具.支持创建.克隆.提交.pus ...

  10. python-9-IO编程

    1-文件读写 f = open('d:/file.txt','r') #如果文件不存在会报异常 print(f.read()) #一次性读取所有内容 f.close() 1.2 由于文件操作会用异常, ...