欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1177


题意概括

  在一个n*m的矩阵中,每一个位置一个数字。

  现在让你选出3个k*k的矩阵,它们互不相交,问最大数值和为多少。

  注意:n,m<=1500


题解

  一开始总想着dp,发现不大可能。

  暴搜也不行。

  然后突然发现,很简单,情况总数非常的少。

  只有以下6种,从3个区域中各选择一个最大的。

  然后就很简单了,我们只需要预处理矩阵前缀和,左上左下右上右下4个方向的前缀max。

  然后对于前两种,分别枚举一下列号和行号;

  对于后四种,只要枚举中间点就可以了。

  所以复杂度为n2。可以过去了。


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=1500+5;
int n,m,k,nn,mm;
int a[N][N],sum[N][N],val[N][N],Row[N],Col[N],LU[N][N],RU[N][N],LD[N][N],RD[N][N];
int main(){
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
memset(sum,0,sizeof sum);
memset(val,0,sizeof val);
memset(Row,0,sizeof Row);
memset(Col,0,sizeof Col);
memset(LU,0,sizeof LU);
memset(RU,0,sizeof RU);
memset(LD,0,sizeof LD);
memset(RD,0,sizeof RD);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
nn=n-k+1,mm=m-k+1;
for (int i=1;i<=nn;i++)
for (int j=1;j<=mm;j++)
val[i][j]=sum[i+k-1][j+k-1]-sum[i-1][j+k-1]-sum[i+k-1][j-1]+sum[i-1][j-1];
for (int i=1;i<=nn;i++)
for (int j=1;j<=mm;j++)
Row[i]=max(Row[i],val[i][j]),Col[j]=max(Col[j],val[i][j]);
for (int i=1;i<=nn;i++)
for (int j=1;j<=mm;j++)
LU[i][j]=max(val[i][j],max(LU[i-1][j],LU[i][j-1]));
for (int i=1;i<=nn;i++)
for (int j=mm;j>=1;j--)
RU[i][j]=max(val[i][j],max(RU[i-1][j],RU[i][j+1]));
for (int i=nn;i>=1;i--)
for (int j=1;j<=mm;j++)
LD[i][j]=max(val[i][j],max(LD[i+1][j],LD[i][j-1]));
for (int i=nn;i>=1;i--)
for (int j=mm;j>=1;j--)
RD[i][j]=max(val[i][j],max(RD[i+1][j],RD[i][j+1]));
int ans=0;
/* ---- ---- ----- ----- ----- -----
|||| |--| | | | |---| | |-| |-| |
---- |--| ----- | | | ----- -----
---- |---| ----- */
for (int i=1;i<=nn;i++){
int Max=0;
for (int j=i+k;j<=nn;j++){
Max=max(Max,Row[j]);
if (j+k>nn)
break;
ans=max(ans,LU[i][mm]+Max+LD[j+k][mm]);
}
}
for (int i=1;i<=mm;i++){
int Max=0;
for (int j=i+k;j<=mm;j++){
Max=max(Max,Col[j]);
if (j+k>mm)
break;
ans=max(ans,LU[nn][i]+Max+RU[nn][j+k]);
}
}
for (int i=k+1;i<=nn;i++)
for (int j=k+1;j<=mm;j++){
int lu=LU[i-k][j-k],ru=RU[i-k][j],ld=LD[i][j-k],rd=RD[i][j];
ans=max(ans,lu+ru+LD[i][mm]);
ans=max(ans,lu+ld+RU[nn][j]);
ans=max(ans,ld+rd+LU[i-k][mm]);
ans=max(ans,rd+ru+LU[nn][j-k]);
}
printf("%d",ans);
return 0;
}

  

BZOJ1177 [Apio2009]Oil 二维前缀和 二维前缀最值的更多相关文章

  1. [BZOJ1177][Apio2009]Oil

    [BZOJ1177][Apio2009]Oil 试题描述 采油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井.被拍卖的整块土地为一个矩形区域,被划分为M ...

  2. bzoj1177 [Apio2009]Oil 二维前缀最大值,和

    [Apio2009]Oil Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2300  Solved: 932[Submit][Status][Disc ...

  3. BZOJ1177:[APIO2009]Oil(枚举,前缀和)

    Description 采油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井.被拍卖的整块土地为一个矩形区域,被划分为M×N个小块. Siruseri地质 ...

  4. C# 数组、一维数组、二维数组、多维数组、锯齿数组

    C#  数组.一维数组.二维数组.多维数组.锯齿数组 一.数组: 如果需要使用同一类型的对象,就可以使用数组,数组是一种数据结构,它可以包含同一类型的多个元素.它的长度是固定的,如长度未知的情况下,请 ...

  5. 【Java学习笔记之八】java二维数组及其多维数组的内存应用拓展延伸

    多维数组声明 数据类型[][] 数组名称; 数据类型[] 数组名称[]; 数据类型数组名称[][]; 以上三种语法在声明二维数组时的功能是等价的.同理,声明三维数组时需要三对中括号,中括号的位置可以在 ...

  6. c#简单实现二维数组和二维数组列表List&lt;&gt;的转置

    刚看到网上一篇文章里用sql实现了行列转置.sql server 2005/2008只用一个pivot函数就可以实现sql server 2000很多行的复杂实现.提到转置,立刻想起还在求学阶段曾经做 ...

  7. saltstack自动化运维系列⑩SaltStack二次开发初探

    saltstack自动化运维系列⑩SaltStack二次开发初探 1.当salt运行在公网或者网络环境较差的条件下,需要配置timeout时间vim /etc/salt/master timeout: ...

  8. “全栈2019”Java第三十一章:二维数组和多维数组详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. c# 一维数组,二维数组,多维数组。

    数组就是给一个变量定义多个字符,可以是string也可以是int.或者说是一组变量. 可以更加方便的操作大量数据. 数组的定义1.数组里面的内容必须是同一类型2.数据必须有长度限制 一维数组 *一.数 ...

随机推荐

  1. [C++]线性链表之顺序表<二>

    /*   @content 线性链表之顺序表   @date 2017-3-21 1:06   @author Johnny Zen  */ /* 线性表     顺序表     链式表[带头指针/不 ...

  2. POJ 1811 Prime Test (Rabin-Miller强伪素数测试 和Pollard-rho 因数分解)

    题目链接 Description Given a big integer number, you are required to find out whether it's a prime numbe ...

  3. python线程之condition

    cond = threading.Condition() # 类似lock.acquire() cond.acquire() # 类似lock.release() cond.release() # 等 ...

  4. js_原生js实现上拉加载更多的功能。

    1.人生啊,是我莽撞了啊.这是我公司一个喜欢读书的女孩子的个性签名,喜欢哪些句子,不悲伤,却切切实实的令人喜好. 2.写程序是一件很直接明了的事情,明白了就是明白了,不懂就是不懂,不懂装懂的会让你走很 ...

  5. [转]find命令之exec

    find是我们很常用的一个Linux命令,但是我们一般查找出来的并不仅仅是看看而已,还会有进一步的操作,这个时候exec的作用就显现出来了. exec解释:    -exec  参数后面跟的是comm ...

  6. android greenDao使用

    github:https://github.com/greenrobot/greenDAO 基本使用:https://toutiao.io/posts/yg1kyu/preview https://b ...

  7. android 基础题

    1. Android的四大组件是哪些,它们的作用? (1).Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很 ...

  8. SANS社区邮件情报收集【2018-12-4到2019-1-19】

    情报来源:注册SANS社区帐号,它提示是否接收邮件咨询等信息,肯定要接收.耳朵听不到东西,天才都变成傻子. 信息点:1.全世界安全员使用它,有培训和免费资源.2.可选择性接收特别网络安全课程,峰会和事 ...

  9. IAR拷贝工程后,修改工程名的方法

    在实际使用过程中,经常基于某个demo进行开发,但是demo的项目名往往不满足新项目的名称,如果重新建立工程,就需要进行一系列的配置,非常麻烦,其实可以直接修改项目名,做法如下; 1. 修改项目目录下 ...

  10. proc文件系统、sysfs文件系统、kobject操作

    Proc文件系统是提供一个接口给用户,让用户可以查看系统运行的一些状态信息,让用户修改内核的一些参数,比方说printk的打印级别就可以通过proc去修改 Sysfs文件系统, Sysfs is a ...