欢迎访问~原文出处——博客园-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. 《深入理解java虚拟机》第三章 垃圾收集器与内存分配策略

    第三章 垃圾收集器与内存分配策略 3.1 概述 哪些内存需要回收 何时回收 如何回收 程序计数器.虚拟机栈.本地方法栈3个区域随线程而生灭. java堆和方法区的内存需要回收.   3.2 对象已死吗 ...

  2. CSS——margin

    CSS margin 属性 定义和用法 margin 简写属性在一个声明中设置所有外边距属性.该属性可以有 1 到 4 个值. 说明 这个简写属性设置一个元素所有外边距的宽度,或者设置各边上外边距的宽 ...

  3. JavaScript之Dom1|DOM2|DOM3之DOM1【节点层次】

    长文慎读. 导航: 1.节点层次 2.Node类型 3.Document类型 4.Element类型 5.Text类型 6.Comment类型 7.CDATASection类型 8.DocumentT ...

  4. Ubuntu 18.04换国内源 中科大源 阿里源 163源 清华源

    感觉还是18.4好用,所以最近装回了18,感觉现在18的兼容性也还可以了,深度学习的环境配置都没有问题,就是安装软件的时候有点慢,所以想要更新一下源. 第一步: 编辑/etc/apt/sources. ...

  5. CF912E Prime Gift

    传送门 看到\(n\)只有16,可以把这些质数分成两半,然后预处理出这些数相乘得出的小于\(10^{18}\)的所有数,排个序,然后二分最终答案,再用两个指针从前往后和从后往前扫,进行\(two-po ...

  6. shiro授权及自定义realm授权(七)

    1.授权流程

  7. 【逆向知识】动态调试技巧-C++代码逆向

    1.C++类代码的特点 寄存器ECX传参时一般用作this指针(对象地址)或是计数器. 有ecx传参的call,是成员函数,构造函数,析构函数 能访问成员变量的函数都会有ecx传参 静态函数.全局函数 ...

  8. Linux系统无线网卡的安装【转】

    转自:http://www.linuxidc.com/Linux/2013-03/81473.htm 现在的很多的可移动无线网卡都是usb接口的,把这种网卡应用到windows操作系统上是很容易就能起 ...

  9. 在docker中部署centos7镜像

    本篇文章参考自: https://www.cnblogs.com/linjj/p/5606911.html https://blog.csdn.net/u012767761/article/detai ...

  10. 通达OA系统优化-对mysql数据库减肥

    OA系统冗余数据过多,访问效率受到影响,现需要对历史数据进行一次清理,以提高OA访问速度 大的数据主要体现在流程上,流程数据主要放在flow_run,flow_run_data,flow_run_pr ...