题意:有一个n*m的矩阵,每个矩阵里有一个数字a[i][j]。现在要求将其中一个格子的值改为p,使得修改后矩阵的最大子矩阵和最小,求这个最小值

n,m<=150,abs(a[i][j])<=1e3

思路:学习cf,也把这种题叫DP了……

考虑如何快速求出修改后最大子矩阵的值

最大子矩阵有一个O(n^3)的写法:枚举所处的两行或两列,剩下的就当做最大子串做

用这样的方法预处理出上下左右四个方向的最大子矩阵之后,枚举任意一个原最大子矩阵中每个点是否修改

如果有多个最大子矩阵除非枚举到重叠部分否则答案不会改变

枚举后的答案即为原最大子矩阵的值修改后的值与上下左右四个方向的max取max

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<bitset>
typedef long long ll;
using namespace std;
#define N 160
#define oo 10000000
#define MOD 100000073 int s[N][N],a[N][N],U[N],D[N],L[N],R[N]; int calc(int x1,int y1,int x2,int y2)
{
return s[x2][y2]-s[x1-][y2]-s[x2][y1-]+s[x1-][y1-];
} int main()
{
//freopen("hihocoder1634.in","r",stdin);
//freopen("hihocoder1634.out","w",stdout);
int n,m,p;
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) scanf("%d",&a[i][j]);
memset(s,,sizeof(s));
for(int i=;i<=n+;i++) U[i]=D[i]=-oo;
for(int i=;i<=m+;i++) L[i]=R[i]=-oo;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) s[i][j]=s[i-][j]+s[i][j-]-s[i-][j-]+a[i][j];
int ans=-oo;
for(int i=;i<=n;i++)
{
int tmp=-oo;
for(int j=;j<=i;j++)
{
int t=;
for(int k=;k<=m;k++)
{
t+=calc(j,k,i,k);
tmp=max(tmp,t);
if(t<) t=;
}
}
U[i]=max(U[i-],tmp);
ans=max(ans,U[i]);
} for(int i=n;i>=;i--)
{
int tmp=-oo;
for(int j=i;j<=n;j++)
{
int t=;
for(int k=;k<=m;k++)
{
t+=calc(i,k,j,k);
tmp=max(tmp,t);
if(t<) t=;
}
}
D[i]=max(D[i+],tmp);
} for(int i=;i<=m;i++)
{
int tmp=-oo;
for(int j=;j<=i;j++)
{
int t=;
for(int k=;k<=n;k++)
{
t+=calc(k,j,k,i);
tmp=max(tmp,t);
if(t<) t=;
}
}
L[i]=max(L[i-],tmp);
} for(int i=m;i>=;i--)
{
int tmp=-oo;
for(int j=m;j>=i;j--)
{
int t=;
for(int k=;k<=n;k++)
{
t+=calc(k,i,k,j);
tmp=max(tmp,t);
if(t<) t=;
}
}
R[i]=max(R[i+],tmp);
} int sx=,sy=,ex=,ey=;
for(int i=;i<=n;i++)
for(int j=i;j<=n;j++)
{
if(sx) break;
int tmp=-oo;
int t=;
int st=;
for(int k=;k<=m;k++)
{
t+=calc(i,k,j,k);
tmp=max(tmp,t);
if(tmp==ans)
{
sx=i; ex=j;
sy=st; ey=k;
break;
}
if(t<)
{
t=;
st=k+;
}
}
}
//printf("ans=%d\n",ans);
//printf("%d %d %d %d\n",sx,sy,ex,ey);
int cnt=ans;
for(int i=sx;i<=ex;i++)
for(int j=sy;j<=ey;j++) cnt=min(cnt,max(ans-a[i][j]+p,max(max(max(U[i-],D[i+]),L[j-]),R[j+])));
printf("%d\n",cnt);
}
return ;
}

最新文章

  1. PE文件格式(加密与解密3)(一)
  2. Opencv step by step - 基本数据类型
  3. Echarts个人实例
  4. Ubuntu 16.04 LTS U盘安装要点
  5. orcale 修改字段属性
  6. SQL Server数据库连接类SQLHelper.cs
  7. TextView控件
  8. vector::erase returns incompatible iterator in debug build
  9. Linux进程或线程绑定到CPU
  10. Spring-bean作用域scope详解
  11. LoadRunner常用方法
  12. Maven之阿里云镜像仓库配置
  13. Spring mvc后台重定向页面,实际前端不跳转
  14. django2.0再写一行代码
  15. 【code block】局部代码块+构造代码块+静态代码块
  16. tesseract安装及问题处理
  17. All You Can Code 2008 (Romanian Contest) A - Tree Search
  18. 图片上传预览js
  19. js中去除字符串两边的空格
  20. mysql通过“延迟关联”进行limit分页查询优化的一个实例

热门文章

  1. git出现误修改如何撤销
  2. PHP 批量操作 Excel
  3. 学习python第二天 流程判断
  4. unix gcc编译过程
  5. 记忆化搜索:POJ1088-滑雪(经典的记忆化搜索)
  6. hadoop 启动or运行mr错误
  7. 访问tomcat出现HTTP Status 500 - java.lang.IllegalStateException: No output folder
  8. 新手用WPF山寨QQ管家7.6(三)
  9. python django 路由系统
  10. Django Rest Framework threoy