【CZY选讲·最大子矩阵和】
题目描述
有一个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选讲·最大子矩阵和】的更多相关文章
- 【CZY选讲·Hja的棋盘】
题目描述 Hja特别有钱,他买了一个×的棋盘,然后Yjq到这个棋盘来搞事.一开始所有格子都是白的,Yjq进行次行操作次列操作,所谓一次操作,是将对应的行列上的所有格子颜色取反.现在Yjq希望搞事之后 ...
- 【CZY选讲·吃东西】
题目描述 一个神秘的村庄里有4家美食店.这四家店分别有A,B,C,D种不同的美食.LYK想在每一家店都吃其中一种美食.每种美食需要吃的时间可能是不一样的.现在给定第1家店A种不同的美食所需要吃的时间 ...
- 【CZY选讲·一道图论神题】
题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只有点权. LYK想把这个图删干净,它的方法是这样的.每次选择一个点,将它删掉,但删这个点是需要代价的 ...
- 【CZY选讲·Yjq的棺材】
题目描述 Yjq想要将一个长为宽为的矩形棺材(棺材表面绝对光滑,所以棺材可以任意的滑动)拖过一个L型墓道. 如图所示,L型墓道两个走廊的宽度分别是和,呈90°,并且走廊的长度远大于. 现在Hja ...
- 【CZY选讲·逆序对】
题目描述 LYK最近在研究逆序对. 这个问题是这样的. 一开始LYK有一个2^n长度的数组ai. LYK有Q次操作,每次操作都有一个参数k.表示每连续2^k长度作为一个小组.假设 n=4,k= ...
- 【CZY选讲·Triangle】
题目描述 长度为的铁丝,你可以将其分成若干段,并把每段都折成一个三角形.你还需要保证三角形的边长都是正整数并且三角形两两相似,问有多少种不同的分法. 数据范围 1≤≤10^6 题解: ①相 ...
- 【CZY选讲·棋盘迷宫】
题目描述 一个N*M的棋盘,’.’表示可以通过,’#’表示不能通过,给出Q个询问,给定起点和终点,判断两点是否联通,如联通输出“Yes”,否则输出“No”. 数据范围 N,M <=500,Q ...
- 【CZY选讲·扩展LCS】
题目描述 给出两个仅有小写字母组成的字符串str1 和str2,试求出两个串的最长公共子序列. 数据范围 |str1| ⩽ 1000; |str2| ⩽ 10^6 题解: ①直接进行LCS( ...
- 【CZY选讲·次大公因数】
题目描述 给定n个数ai,求sgcd(a1,a1),sgcd(a1,a2),…,sgcd(a1,an). 其中sgcd(x,y)表示x和y的次大公因数.若不存在次大公因数,sgcd(x,y)=-1 ...
随机推荐
- nodejs的http-server--web前端福利
很多web前端在日常开发的时候可能会想常开发是谁. 不好意思,说错了. 很多web前端在日常开发的时候总是避免不了让所写页面在服务器环境下执行. 比如当你在用angularjs的route模块等等等. ...
- Web前端开发面试技巧
Web前端开发面试技巧 面试前端工程师对我来说是一件非常有意思的事,因为面试过程很大程度上也是自我提升的过程.无论大公司还是小公司,之所以在如何招聘到真正有能力的,前端工程师方面会遇到同样的问题. 近 ...
- linux 安装mysql5.6 yum
安装mysql: 查看mysql: rpm -qa | grep -i mysql 安装必要的环境 yum -y install gcc gcc-c++ ncurses-devel perl 查看环境 ...
- linux poll用法
相对于select来说,poll 也是在指定时间内论询一定数量的文件描述符,来测试其中是否有就绪的,不过,poll 提供了一个易用的方法,来实现 i/o 复用. 声明如下: #include < ...
- PHP代码审计3-SQL注入,CSRF,动态函数执行与匿名函数执行,unserialize 反序列化漏洞,变量覆盖,文件管理,文件上传
SQL注入 审计语句 [输入参数] SELECT,DELETE,UPDATE,INSERT 防御 转义: 1.开启gpc:判断解析用户提示的数据 2.mysql_real_escape_string( ...
- format内置函数
1. 函数功能将一个数值进行格式化显示. 2. 如果参数format_spec未提供,则和调用str(value)效果相同,转换成字符串格式化. >>> format(3.14159 ...
- Androd安全——混淆技术完全解析
.前言 在上一篇Androd安全--反编译技术完全解析中介绍了反编译方面的知识,因此我们认识到为了安全我们需要对代码进行混淆. 混淆代码并不是让代码无法被反编译,而是将代码中的类.方法.变量等信息进行 ...
- 理解Queue队列中join()与task_done()的关系
在网上大多关于join()与task_done()的结束原话是这样的: Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号 ...
- elasticsearch索引和映射
目录 1. elasticsearch如何实现搜索 1.1 搜索实例 1.2 es中数据的类型 1.3 倒排索引 1.4 分析与分析器 1.4.1 什么是分析器 1.4.2 内置分析器种类 1.4.3 ...
- Spark 的情感分析
Spark 的情感分析 本文描述了基于 Spark 如何构建一个文本情感分析系统.文章首先介绍文本情感分析基本概念和应用场景,其次描述采用 Spark 作为分析的基础技术平台的原因和本文使用到技术组件 ...