IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> HDU 6957.Maximal submatrix -> 正文阅读

[数据结构与算法]HDU 6957.Maximal submatrix

Issue:

在这里插入图片描述

Thinking:

  1. 题目要求最大子矩阵的面积,就可以把每一行看做是直方图中最大矩形问题,这题马氏风格,暴力枚举每一行
  2. 把每一行中非递减的“矩形”用h[][]数组存下来,这样每一行都是一个直方图中最大矩形问题
  3. 问题转化为直方图中最大矩形问题,依次枚举每一列,算出每一列能够向左和向右能够到达的最大长度分别用l[]和r[]数组记录,这一步就可以用单调栈来优化,时间复杂度为O(n)
  4. 每一行的公示就是(h[i] * (l[i] + r[i] - 1))
  5. 最后,对每一个结果取max
  6. 别忘了多组数据测试,所以每一次都要清空h[][]数组

Algorithm:

二维单调栈

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> 

using namespace std;

typedef long long LL;

const int N = 2e3 + 10;

//a[][]记录矩阵数据,h[][]记录当前这个点向上的最大非递减矩阵的高度
//q[]是单调栈数组,l[]和r[]记录向左(向右)的最远距离 
//q[],l[],r[]存的是j坐标 
int a[N][N], h[N][N], q[N], l[N], r[N]; 
int tt;  //tt是单调栈的指针 

int main()
{
	int T;
	scanf("%d", &T);
	
	while (T -- )  //多组测试数据 
	{
		int n, m;
		scanf("%d%d", &n, &m);
		memset(h, 0, sizeof h);  //每组测试数据都清空h数组
		for (int i = 1; i <= n; i ++ )
			for (int j = 1; j <= m; j ++ )
			{
				scanf("%d", &a[i][j]);  //写入矩阵数据 
				if (a[i][j] >= a[i - 1][j]) h[i][j] = h[i - 1][j] + 1;  //如果当前列非递减,矩阵高度+1 
				else h[i][j] = 1;  //递减了就要从1重新开始 
			} 
		
		LL ans = 0;  //答案 
		for (int i = 1; i <= n; i ++ )  //枚举每一行 
		{
			tt = -1;
			q[ ++ tt ] = 0;  //开始初始化单调栈,从左到右算出l[]数组的值
			for (int j = 1; j <= m; j ++ )
			{
				while (h[i][q[tt]] >= h[i][j]) tt -- ;  //大于栈顶元素,弹出
				l[j] = j - q[tt];
				q[ ++ tt] = j;
			}
			
			tt = -1;
			q[ ++ tt] = m + 1;  //这里q[0]和q[n+1]的高度都是0,和h数组中的元素都>=1
			                    //这样初始化有好处,保证了每一个矩阵的左边(右边)都有小于它高度的元素
								//而来又减少了是否栈为空的判断 
								//最大列+1,m + 1 
			for (int j = m; j; j -- )  //没矩右边的时候要倒过来,j --  
			{
				while (h[i][q[tt]] >= h[i][j]) tt -- ;  //>=是因为一样高度的矩阵是可以被算入面积的,不能被算入面积的元素要严格小
				r[j] = q[tt] - j;  //j这个位置被算了两遍,所以后面的公式要 -1
				q[ ++ tt] = j;  //单调栈的模板操作 
			} 
			
			for (int j = 1; j <= m; j ++ ) ans = max(ans, (LL)h[i][j] * (l[j] + r[j] - 1)); 
		}
		printf("%lld\n", ans);
	}
	return 0;
} 

Tips:

  1. 这是完全马师傅风格的代码,感觉从一开始无从下手,到超时,到最后的Ac,中间改了几次,觉得深入学习算法的进步是可以看得到的
  2. 差点忘记了这题的特点,一来题目是要算面积,二来也是要找左右两边最小的数,就是典型的二维单调栈模型
  3. 现在自己的水平还是很low,从题目还读不懂,到看懂样例,到尝试多发WA,到看题解整理出自己的思路,到写出ac代码,到完成博客,一共要花4个小时,速度很慢,希望多次写博客后,速度能够有所提升
  4. 还是国豪哥对我说的:算法竞赛,贵在坚持!
  5. 最后紧跟一下时事:吴签到,亦值WA,凡死了!
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-27 16:29:50  更:2021-07-27 16:31:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:26:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码