最大子矩阵求法详解

最大子矩阵( $ s^2 $ 枚举障碍与 $ n \times m $ 悬线法)

题目大意:

有 $ s $ 个障碍分布在一个 $ n\times m $ 的矩阵中。现在让你找出其中不包含任何一个障碍的最大子矩阵。



首先我们要引进一个新概念:(极大子矩阵:所有边都不能再向外扩张的合法矩阵 )(极大化思想:最大子矩阵一定是一个极大子矩阵

$ solution~1:~O(s^2) $

首先讲一个 $ O(s^5) $ 算法:枚举两个对角端点(就是四个边界),然后枚举障碍判断这个矩阵是否合法。这个算法很不优,因为它枚举了很多不是极大子矩阵的矩阵,就是个纯暴力。

所以我们优化一下 $ O(s^3) $ :枚举左右边界,然后将边界内的点按y轴排序,每两个相邻的点和左右边界组成一个合法矩阵。这个算法也枚举了左右边界,会产生非极大子矩阵的矩阵。

所以我们需要找到一种枚举方案,使得(矩阵合法)(极大子矩阵)两个条件尽量满足,于是:

为了不做多余运算,我们以点为边界 $ O(s^2) $ :将点按照横坐标排序,依次枚举每一个点作为矩阵的左边界(只要左边界再向左移就会碰到这个点),然后我们枚举它右边的点作为右边界,并在枚举同时更新上下边界。(因为一个合法的矩阵不能有障碍,所以枚举的这些点会限制上下边界(上下边界以外的矩阵不用考虑,因为他们的左边界不是当前的最外层枚举的那个点所限制的,也就是说它们的左边界不是当前枚举的左边界))。不过要注意,我们的 $ n \times m $ 的大边界也可作为极大子矩阵的边界,所以还需要倒着来一遍。

例题:$ POJ~3197~Corral~the~Cows $ (二分,最大子矩阵)

这道题并不是一道正宗的最大子矩阵,但是它同样用到了枚举点的思想,博主刷题不多,先用着凑活一下,大家只需要知道这种方法就行。

$ Code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>#define ll long long
#define db double
#define rg register intusing namespace std;int n,c;struct su{int x,y;inline bool operator <(const su &z)const{return y<z.y;}
}a[505];inline bool cmp (const su &x,const su &y){if(x.x==y.x)return x.y<y.y;return x.x<y.x;
}inline int qr(){register char ch; register bool sign=0; rg res=0;while(!isdigit(ch=getchar()))if(ch=='-')sign=1;while(isdigit(ch))res=res*10+(ch^48),ch=getchar();if(sign)return -res; else return res;
}inline bool check(int x){multiset<su> s; rg res=0;for(rg i=1,j=1;i<=n;++i){while(j<=n&&a[i].x+x-1>=a[j].x)s.insert(a[j]), ++j;multiset<su>::iterator l,r;l=r=s.begin(); res=0;while(l!=s.end()){while(r!=s.end()&&(*r).y-(*l).y+1<=x) ++r,++res;++l; if(res>=c)return 0; --res;}s.erase(s.find(a[i]));}return 1;
}int main(){//freopen(".in","r",stdin);//freopen(".out","w",stdout);c=qr(); n=qr();for(rg i=1;i<=n;++i)a[i].x=qr(),a[i].y=qr();sort(a+1,a+n+1,cmp);rg l=1,r=10000,mid;while(l<=r){mid=(l+r)>>1;if(check(mid))l=mid+1;else r=mid-1;}printf("%d\n",l);return 0;
}


$ solution~2:~O(n\times m) $ 悬线法

这是很早之前学的东西了,就当做个总结:

上文我们已经提到了极大子矩阵,还有一个 $ s^2 $ 做法,但是这个做法在障碍比较多的时候是不行的。所以我们考虑另一种与边界长度有关的最大子矩阵做法。上一种做法里,我们强调让枚举的矩阵尽量是极大子矩阵,这个思想在悬线法中也是核心地位。

我们知道每一个点向上向左向右的合法极大子矩阵有很多个,注意没有向下。所以我们不可能将每个点的向上向左向右的合法极大子矩阵求出来,这样会有大量重复。所以我们钦定从每一个点向上碰到的第一个障碍为上边界,然后向左右尽量延伸,所得到的矩阵为这个点用悬线法得到的矩阵,之所以不向下是为了方便从第一排开始递推寻找这个矩阵。我们可以从这个矩阵的定义里知道,所有极大子矩阵一定都可以用这种方式被找出来(证明:极大子矩阵的上边界的上一排一定有一个障碍,这个障碍一直向下到这个极大子矩阵的下边界所对应的那个点,它用悬线法求出的矩阵就是这个极大子矩阵)。而最大子矩阵被包含在极大子矩阵中,所以悬线法的正确性得到证明。接下来是复杂度和过程详解。

我们需要求出每一个点用悬线法求得的矩阵。为此,我们先求出每个点向左端延伸的最远距离,向右端延伸的最远距离,向上延伸的最远距离。然后开始枚举整个 $ n \times m $ 的矩阵,过程是从第一排向下递推。因为我们求的是一个矩阵,所以当前点在这一排向左向右延伸的最远距离不是所求矩阵的最远距离,它还受到上面几排的左右端的影响(所以我们从第一排向下推)。然后我们这个点用悬线法得到的矩阵的最左端就是它在当前排向左的最远距离和上面那些点到最左端的距离的最小值,这个递推记录一下就好,右端点同理,而矩阵的高从一开始就确定了,然后直接计算就好!

注意:每个点向左端延伸的最远距离,向右端延伸的最远距离,可以边悬线法边求。

例题:洛谷 $ P4147 $ 玉蟾宫

$ Code: $

#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,l[1001][1001],r[1001][1001],h[1001][1001],tot;
int main(){char c;scanf("%d%d",&n,&m);for(i=1;i<=n;i++)for(j=1;j<=m;j++){cin>>c;if(c=='F')h[i][j]=h[i-1][j]+1;}for(i=1;i<=m;i++)r[0][i]=m+1;for(i=1;i<=n;i++){int f=0;for(j=1;j<=m;j++){if(h[i][j])l[i][j]=max(l[i-1][j],f);else f=j;}f=m+1;for(j=m;j>=1;j--){if(h[i][j])r[i][j]=min(r[i-1][j],f);else r[i][j]=m+1,f=j;}for(j=1;j<=m;j++)tot=max(tot,(r[i][j]-l[i][j]-1)*h[i][j]);}cout<<tot*3;return 0;
}

转载于:https://www.cnblogs.com/812-xiao-wen/p/11251533.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263153.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQLSERVER数据仓库的构建与分析

实例构建过程与分析 1&#xff0e;现在以一个比较简单的实例来分析和探讨MS SQL SERVER 数据仓库的构建过程。实际上数据仓的构建是相当复杂的&#xff0c;他结合了数据仓库的前端技术和很强的业务要求。在这儿只是以一个简单的实例来说明他大致的构建流程。 2&#xff0e;构建…

基于Layui实现的树形菜单页面

基于Layui实现的树形菜单页面具体方法实现方法一&#xff1a;针对Layui模板的前后端统一更新1. 删除2. 添加3. 后端方法二&#xff1a;基于Dtree实现的纯前端树形增删改文中的组件地址具体方法实现 实现树形菜单&#xff0c;本文将给出两种实现方式。 针对Layui前端模板EasyW…

POJ 1723 Soldiers (中位数)

$ POJ~1723~Soldiers $ (中位数) $ solution: $ 这道题说难也不算太难&#xff0c;但是当时自己想的很矛盾。所以还是列一篇题解。 这道题首先比较容易看出来的就是&#xff1a;行和列是两个分开的问题&#xff0c;而且行的移动就是一个仓库选址的板子&#xff0c;直接求中位数…

php中时间轴开发,即显示为“刚刚”、“5分钟前”、“昨天10:23”等

php中时间轴开发&#xff0c;即显示为“刚刚”、“5分钟前”、“昨天10:23”等 其实这个没什么技术含量&#xff0c;当然就直接贴代码&#xff0c;不废话了&#xff08;合肥旅游网&#xff09;&#xff0c; 但是在其实开发中还是蛮有用的&#xff0c;譬如论坛帖子&#xff0c;围…

(一)Windows环境下汇编编程读书笔记

看了一节关于80x86系列处理器简史&#xff0c;不知道云里和雾里&#xff0c;什么晶体管啊&#xff0c;什么什么之类的不知道云里和雾里&#xff0c;看了讲什么都不知道啊&#xff01; 转载于:https://www.cnblogs.com/Nuxgod/articles/692990.html

我的读书清单(持续更新)

我的读书清单&#xff08;持续更新&#xff09; 2017-05-31 《一千零一夜》2006&#xff08;四五年级&#xff09;《中华上下五千年》2008&#xff08;初一&#xff09;《鲁滨孙漂流记》2008&#xff08;初二&#xff09;《钢铁是怎样炼成的》2009&#xff08;初二&#xff09;…

Docker知识点总结及其命令的使用

DockerDocker简介Docker与Tomcat有什么区别&#xff1f;Docker与虚拟机有什么区别&#xff1f;Docker的基本组成Docker的联合文件系统Docker基本命令Docker中的几个重要组件一、容器数据卷二、Dockerfile三、Docker网络虚拟机共享网络的三种方式Docker共享网络的四种方式Docker…

主题:Spring注解入门(转载)

原文链接&#xff1a;http://www.iteye.com/topic/295348 1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的 类的实现&#xff1a; Java代码 public class UserManagerImpl implements UserManager { private UserDao userDao; public void …

sql触发器

在SQL Server里面也就是对某一个表的一定的操作&#xff0c;触发某种条件&#xff0c;从而执行的一段程序。触发器是一个特殊的存储过程。 常见的触发器有三种&#xff1a;分别应用于Insert , Update , Delete 事件。 我为什么要使用触发器&#xff1f;比如&#x…

XDJM的情意比山高,比海深!!

又是兄弟姐妹们帮我提前过的生日&#xff0c;我们这帮人从SC出来后还没好好聚过&#xff0c;乘这个机会把大家约了出来。星期五整整一天都很快乐&#xff0c;特别是我&#xff0c;NANA&#xff0c;小乔期待着晚上的聚餐&#xff0c;期待着金贸的蛋糕&#xff0c;嘿嘿。。他们好…

最大子矩阵和

最大子矩阵和 $ n^3 $ 算法 $ solution: $ 首先我们不难想到枚举上下左右边界&#xff0c;然后两层循环统计权值和&#xff0c;复杂度 $ O(n^6) $ 。这个我们用前缀和可以省去后面的循环&#xff0c;将复杂度降成 $ O(n^4) $ 。然后我们考虑不枚举上下左右四个边界&#xff0c;…

Springfox-swagger使用详解

Springfox-swagger使用详解什么是Swagger&#xff1f;Swagger的具体使用一、导入依赖二、建立Swagger配置类三、通过Swagger测试接口引用什么是Swagger&#xff1f; 是一个开源的API Doc的框架可以将我们的Controller中的API方法以文档的形式展现&#xff0c;并支持为其添加注…

Android中调用系统已安装的播放器来播放网络流媒体视频

2019独角兽企业重金招聘Python工程师标准>>> 实现思路比较简单几行代码就可以搞定&#xff0c;在界面放一个Button或者带有播放图标的imageview&#xff0c;点击事件中调用本地播放器来播放。 Uri uri Uri.parse("http://218.200.69.66:8302/upload/Media/20…

繁体机文本转换

Encoding big5 Encoding.GetEncoding("big5");Encoding abc Encoding.Default;string s "い瓣.約狥 ";byte[] t Encoding.Convert(big5,abc,abc.GetBytes(s));MessageBox.Show( abc.GetString(t));转载于:https://www.cnblogs.com/frhua/archive/2007/…

数据批量写入

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data;using System.Data.SqlClient;using System.Reflection;using System.Collections;namespace SQLBulkInsertTest{/// <summary>/// 测试数据批量插入 By RhythmK…

WireShark详解

WireShark详解Wireshark介绍Wireshark使用一、基础数据说明二、指定数据包过滤Wireshark安装Wireshark介绍 Wireshark是一款可以运行在多平台的网络抓包工具&#xff0c;可以嗅探通过本机网卡的各类网络包&#xff0c;并对它们的协议&#xff0c;源、目标地址等多种数据进行解…

多图上传 - Web Uploader

http://fex.baidu.com/webuploader/ 官方DEMO&#xff0c;我都不想说了&#xff0c;各种问题。参考ShuaiBi文章 http://www.cnblogs.com/ismars/p/4176912.html 用了bootstrap 代码百度网盘地址&#xff1a;http://pan.baidu.com/s/1pJkj9wf 自己参照改改就好了。 //所有文件上…

Access导入文本文件的Schema.ini文件格式

Schema.ini格式如下&#xff08;参考&#xff1a;MSDN主题 Schema.ini File&#xff09;&#xff1a; Schema.ini用于提供文本数据中的记录规格信息。每个Schema.ini的条目用于指明表的5个特征之一&#xff1a; 文本文件名 文件名有方括号括起来&#xff0c;例如如果要对Sampl…

[开发手记] 使用.NET实现你的IP切换器

发布日期&#xff1a;2007.4.17 作者&#xff1a;Anytao ©2007 Anytao.com 转贴请注明出处&#xff0c;留此信息。 下载&#xff1a;[Anytao.IPHelper][代码下载&#xff0c;近期上传] 本文将介绍以下内容&#xff1a; • 批处理文件应用 • 调用外部应用 • 文件处理…

Linux文件读写改权限详解

Linux文件读写改权限详解文件的rwx权限 [ r ][ w ][ x ]该文件可读(read)该文件可修改(write)该文件可执行(execute) 注意&#xff1a;只有当该文件所在目录有写权限&#xff0c;并且该文件有[w]权限&#xff0c;才可以进行删除操作 目录的rwx权限 [ r ][ w ][ x ]可查看目录…