最大矩阵面积问题

news2025/1/20 7:05:40

问题概述

最大矩阵面积问题有两种:

  1. 在一个网格图中,一些格子有障碍,求在网格图中规划一个矩形,使得它不会覆盖任何一个障碍格且面积最大。
  2. 在一个平面直角坐标系中,先给你规定一个大矩形(一般左下角是 ( 0 , 0 ) (0, 0) (0,0),右上角是 ( M a x X , M a x Y ) (MaxX, MaxY) (MaxX,MaxY)),有一些障碍点,求在这个大矩形中规划一个小矩形,使得它不会覆盖每一个障碍点(障碍点可在矩形边缘)。

具体问题

对于第一个类型:洛谷 P4147 玉蟾宫
对于第二个类型:洛谷 P1578 奶牛浴场


解法

1.悬线法

一般用在方格图中,时间复杂度为整个方格图大小 O ( n m ) O(nm) O(nm)
h i , j h_{i,j} hi,j 表示从 ( i , j ) (i, j) (i,j) 出发,向上拓展,成一个左右宽度一格的细长矩形的高度
如下图:
(学校机房图片上传不上去,先鸽着)

再设 l i , j ,   r i , j l_{i, j},\space r_{i, j} li,j, ri,j 为以这个细长矩形为中轴线,向左、向右拓展,遇到第一个障碍格的列坐标(没有的话就分别设为 0 0 0 m + 1 m + 1 m+1)。
如下图:
(同上)

枚举每个格子,求出每个 h i , j , l i , j , r i , j h_{i,j},l_{i,j},r_{i,j} hi,j,li,j,ri,j 的值,最后用 h i , j × ( r i , j − 1 − l i , j ) h_{i,j} \times (r_{i, j} - 1 - l_{i,j}) hi,j×(ri,j1li,j) 来更新最大面积 a n s ans ans

下面给出玉蟾宫代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e3 + 7;

int n, m, ans = 1;
char g[maxn][maxn];
// l[i][j]:(i, j)向左能到达最远的地方
// r[i][j]:(i, j)向右能到达最远的地方
// h[i][j]:(i, j)向上能到达最远的地方
// ans = max(ans, (r[i][j] - l[i][j] + 1) * h[i][j])

// 看看是不是全是 R
bool check() {
	for (int  i = 1; i <= n; i++)
	    for (int j = 1; j <= m; j++)
		    if (g[i][j] != 'R')
			    return false;
	return true;
}
int l[maxn][maxn], r[maxn][maxn], h[maxn][maxn];
int main() {
    scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> g[i][j];
			h[i][j] = 1, l[i][j] = r[i][j] = j;
		}

		for (int j = 2; j <= m; j++) 
			if (g[i][j - 1] == 'F' && g[i][j] == 'F')
			    l[i][j] = l[i][j - 1];
		
		for (int j = m - 1; j >= 1; j--) 
			if (g[i][j + 1] == 'F' && g[i][j] == 'F')
			    r[i][j] = r[i][j + 1];
		
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (g[i][j] == 'F' && g[i - 1][j] == 'F' && i > 1) {
				h[i][j] = h[i - 1][j] + 1;
				if (l[i - 1][j] > l[i][j])
				    l[i][j] = l[i - 1][j];
				if (r[i - 1][j] < r[i][j])
				    r[i][j] = r[i - 1][j];
			  /*
                R F R
				F F F
                (2, 2)为当前所在位置,
				l[2][2]原本等于1, r[2][2]原本等于3,
                但由于g[1][2] == 'F', 符合 h 更新要求,
				所以l[2][2]更新为2, r[2][2]更新为2.
			  */
			}
			ans = max(ans, (r[i][j] - l[i][j] + 1) * h[i][j]);
		  /* 
		    当l[2][2] == 2, r[2][2] == 2, h[2][2] == 2时,
			答案显然不是最优,
            当循环扫到(2, 1)时,
			l[2][1] == 1, r[2][1] == 3, h[2][1] == 1,
			答案最优.
		  */
		}
	}
	// 特判是否全为 R
    if (check())printf("0\n");
	else printf("%d\n", ans * 3);
	return 0;
}

当然还可以用单调站求 h i , j , l i , j , r i , j h_{i,j},l_{i,j},r_{i,j} hi,j,li,j,ri,j

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 1e3 + 7;
const int inf  = 0x3f3f3f3f;

int n, m;
bool a[maxn][maxn];
int h[maxn][maxn];
int l[maxn][maxn], r[maxn][maxn];
int sta[maxn], top;
int ans;
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) 
    	for (int j = 1; j <= m; ++j) {
    		char c; cin >> c;
    		a[i][j] = (c == 'F');
		}
    		
    for (int i = 1; i <= n; ++i) {
    	for (int j = 1; j <= m; ++j) 
    		if (a[i][j]) h[i][j] = h[i - 1][j] + 1;
    		
    	top = 0;
		for (int j = 1; j <= m; ++j) {
			while (top > 0 && h[i][sta[top]] > h[i][j]) {
				r[i][sta[top]] = j;
				--top;
			}
			sta[++top] = j;
		}
		while (top > 0) {
			r[i][sta[top]] = m + 1;
			--top;
		}
		
		top = 0;
		for (int j = m; j >= 1; --j) {
			while (top > 0 && h[i][sta[top]] > h[i][j]) {
				l[i][sta[top]] = j;
				--top;
			}
			sta[++top] = j;
		}
		while (top > 0) {
			l[i][sta[top]] = 0;
			--top;
		}
		
		for (int j = 1; j <= m; ++j)
		    ans = max(ans, h[i][j] * (r[i][j] - 1 - l[i][j]));
	}
	// 这个不用特判
	// 因为若全是 R, 每一个 h[i][j] 都为 0
	printf("%d\n", ans * 3);
	return 0;
} 

2.障碍点法

一般用在平面直角坐标系中,时间复杂度与障碍点个数有关,为 O ( n 2 ) O(n^2) O(n2)
可以看看这篇题解。

#include <bits/stdc++.h>

#define mkpr make_pair

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 5e3 + 7;

int L, W, n;
struct point {
    int x, y;
    point() {}
    point(int _x, int _y) : x(_x), y(_y) {}
} p[maxn];
bool cmp1(point a, point b) {return a.x < b.x;}
bool cmp2(point a, point b) {return a.y < b.y;}
int ans;
int main() {
    scanf("%d%d%d", &L, &W, &n);
    for (int i = 1; i <= n; ++i)
    	scanf("%d%d", &p[i].x, &p[i].y);
    p[++n] = point(0, 0), p[++n] = point(L, 0);
    p[++n] = point(0, W), p[++n] = point(L, W);
    
    sort(p + 1, p + n + 1, cmp1);
    // 从左往右扫 
    for (int i = 1; i <= n; ++i) {
    	int up = W, down = 0;
        for (int j = i; j <= n; ++j) {
        	while (p[i].x == p[j].x && j <= n) ++j;
        	if (j > n) break;
        	ans = max(ans, (up - down) * (p[j].x - p[i].x));
        	if (p[i].y <= p[j].y) up = min(up, p[j].y);
        	if (p[i].y > p[j].y) down = max(down, p[j].y);
		}
	}
    // 从右往左扫
  	for (int i = n; i >= 1; --i) {
  		int up = W, down = 0;
          for (int j = i; j >= 1; --j) {
          	while (p[i].x == p[j].x && j >= 1) --j;
          	if (j < 1) break;
          	ans = max(ans, (up - down) * (p[i].x - p[j].x));
          	if (p[i].y <= p[j].y) up = min(up, p[j].y);
          	if (p[i].y > p[j].y) down = max(down, p[j].y);
  		}	
  	}
	
  	sort(p + 1, p + n + 1, cmp2);
  	// 特殊情况:小矩形左右边与大矩形左右边重合 
  	for (int i = 1; i <= n - 1; ++i)
        ans = max(ans, L * (p[i + 1].y - p[i].y)); 
        
	printf("%d\n", ans);
	return 0;
}

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

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

相关文章

搭建一个基于Spring Boot的数码分享网站

搭建一个基于Spring Boot的数码分享网站可以涵盖多个功能模块&#xff0c;例如用户管理、数码产品分享、评论、点赞、收藏、搜索等。以下是一个简化的步骤指南&#xff0c;帮助你快速搭建一个基础的数码分享平台。 — 1. 项目初始化 使用 Spring Initializr 生成一个Spring …

迅为RK3576开发板Android 多屏显示

迅为iTOP-3576开发板采用瑞芯微RK3576高性能、低功耗的应用处理芯片&#xff0c;集成了4个Cortex-A72和4个Cortex-A53核心&#xff0c;以及独立的NEON协处理器。它适用于ARM PC、边缘计算、个人移动互联网设备及其他多媒体产品。 1.1 Android 多屏同显 iTOP-RK3576 开发板支持…

gather算子的CUDA编程和算子测试

知乎介绍参考添加链接描述 完整测试框架参考本人仓库 添加链接描述 gather算子的onnx定义参考添加链接描述,该算子的主要变换参考下图: 这里我们不妨以input = [A, dimsize, D], indices = [B,C], axis = 1举例子,此时对应的output形状是[A,B,C,D],并且根据gather算子定…

深度学习 Pytorch 张量的线性代数运算

pytorch中并未设置单独的矩阵对象类型&#xff0c;因此pytorch中&#xff0c;二维张量就相当于矩阵对象&#xff0c;并且拥有一系列线性代数相关函数和方法。 在实际机器学习和深度学习建模过程中&#xff0c;矩阵或者高维张量都是基本对象类型&#xff0c;而矩阵所涉及到的线…

Linux下构建OpenEuler22.03+Nginx的Docker镜像

1. 制作OpenEuler22.03的Docker镜像 首先&#xff0c;下载OpenEuler20.03的镜像压缩包&#xff1a; 下载链接为&#xff1a; https://mirrors.aliyun.com/openeuler/openEuler-22.03-LTS/docker_img/x86_64/openEuler-docker.x86_64.tar.xz 这里我们可以顺便下载一下对应的…

Coder星球-测试用例设计

项目介绍 Coder星球是一个前后端分离的开源技术交流平台&#xff0c;包括管理后台和web前端&#xff0c;旨在打造一个互相交流技术并共同进步的平台。 项目功能结构图 测试用例 1.登录 2.注册 3.文章发布 4.点赞 5.评论

wow-agent---task2使用llama-index创建Agent

一&#xff1a;创造俩个函数&#xff0c;multiply和add作为fuction calling被LLM当做工具来使用&#xff0c;实现计算一个简单的计算题&#xff1a; from llama_index.llms.ollama import Ollama from llama_index.core.agent import ReActAgent from llama_index.core.tools …

React的应用级框架推荐——Next、Modern、Blitz等,快速搭建React项目

在 React 企业级应用开发中&#xff0c;Next.js、Modern.js 和 Blitz 是三个常见的框架&#xff0c;它们提供了不同的特性和功能&#xff0c;旨在简化开发流程并提高应用的性能和扩展性。以下是它们的详解与比较&#xff1a; Next、Modern、Blitz 1. Next.js Next.js 是由 Ve…

Git - 将指定文件夹或文件忽略(无论添加缓存区或提交都不会显示)

前言 有些时候&#xff0c;我们 不希望 项目有些文件夹被 Git “监控” 起来&#xff0c;而是与 Git 毫无关系。 第一步 注意&#xff1a;touch 与 . 之间有空格。 在 Gitbash 命令窗口中&#xff0c;输入以下命令&#xff1a; touch .gitignore此时&#xff0c;你的项目文件…

HTML5+Canvas实现的鼠标跟随自定义发光线条源码

源码介绍 HTML5Canvas实现的鼠标跟随自定义发光线条特效源码非常炫酷&#xff0c;在黑色的背景中&#xff0c;鼠标滑过即产生彩色变换的发光线条效果&#xff0c;且线条周围散发出火花飞射四溅的粒子光点特效。 效果预览 源码如下 <!DOCTYPE html PUBLIC "-//W3C//D…

C++:bfs解决多源最短路与拓扑排序问题习题

1. 多源最短路 其实就是将所有源头都加入队列&#xff0c; 01矩阵 LCR 107. 01 矩阵 - 力扣&#xff08;LeetCode&#xff09; 思路 求每个元素到离其最近0的距离如果我们将1当做源头加入队列的话&#xff0c;无法处理多个连续1的距离存储&#xff0c;我们反其道而行之&…

Java基础--类和对象

目录 什么是类&#xff1f; 什么是对象 为什么java会设计对象 Java对象该怎么用 程序执行流程 类的加载顺序 什么是类&#xff1f; 类是构建对象的模板&#xff0c;一个类可以创建多个对象&#xff0c;每个对象的数据的最初来源来自对象 public class Student{public in…

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证6)

重新创建WebApi项目&#xff0c;安装Microsoft.AspNetCore.Authentication.JwtBearer包&#xff0c;将之前JwtBearer测试项目中的初始化函数&#xff0c;jwt配置类、token生成类全部挪到项目中。   重新编写login函数&#xff0c;之前测试Cookie和Session认证时用的函数适合m…

Electron实践继续

文章目录 前言一、知识储备前提二、开发工具集&#xff08;一&#xff09;代码编辑器之选&#xff08;二&#xff09;命令行工具运用&#xff08;三&#xff09;Git 与 GitHub 协作利器&#xff08;四&#xff09;Node.js 与 npm 核心环境 你的第一个Electron应用程序 前言 上…

《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统

和组合导航一样&#xff0c;也可以通过预积分 IMU 因子加上雷达残差来实现基于预积分和图优化的紧耦合 LIO 系统。一些现代的 Lidar SLAM 系统也采用了这种方式。相比滤波器方法来说&#xff0c;预积分因子可以更方便地整合到现有的优化框架中&#xff0c;从开发到实现都更为便…

【CSS】---- CSS 实现超过固定高度后出现展开折叠按钮

1. 实现效果 2. 实现方法 使用 JS 获取盒子的高度&#xff0c;来添加对应的按钮和样式&#xff1b;使用 CSS 的浮动效果&#xff0c;参考CSS 实现超过固定高度后出现展开折叠按钮&#xff1b;使用容器查询 – container 语法&#xff1b;使用 clamp 函数进行样式判断。 3. 优…

【C语言】_字符串拷贝函数strcpy

目录 1. 函数声明及功能 2. 使用示例 3. 注意事项 4. 模拟实现 4.1 第一版&#xff1a;基本功能判空const修饰 4.2 第二版&#xff1a;优化对于\0的单独拷贝 4.3 第三版&#xff1a;仿strcpy的char*返回值 1. 函数声明及功能 char * strcpy ( char * destination, cons…

大文件上传服务-后端V1V2

文章目录 大文件上传概述:minio分布式文件存储使用的一些技术校验MD5的逻辑 uploadV1 版本 1uploadv2 版本 2 大文件上传概述: 之前项目做了一个文件上传的功能,最近看到有面试会具体的问这个上传功能的细节&#xff0c;把之前做的项目拿过来总结一下&#xff0c;自己写的一个…

【k8s面试题2025】1、练气期

主要通过呼吸吐纳等方法&#xff0c;将外界的天地灵气吸入体内&#xff0c;初步改造身体&#xff0c;使身体素质远超常人。 文章目录 docker 和虚拟机的不同Kubernetes 和 docker 的关系Kube-proxy IPVS 和 iptables 的异同蓝绿发布Kubernetes中常见的数据持久化方式关于 Docke…

快速入门:如何注册并使用GPT

文章目录 ProtonMail邮箱步骤 1&#xff1a;访问Proton官网步骤 2&#xff1a;创建ProtonMail账户步骤 3&#xff1a;选择注册免费账户步骤 4&#xff1a;填写邮箱地址和手机号&#xff08;可选&#xff09;步骤 5&#xff1a;邮箱验证&#xff08;必须进行验证&#xff09;步骤…