最大长方形(二)

本文探讨了求解最大长方形面积的问题,介绍了两种方法:一种是基于分治策略的算法,另一种是采用单调队列的高效解决方案。通过具体代码示例详细解释了这两种方法的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=258

解题思路:求最大长方形面积,就是求某一个高度和这个高度最大连续长度的乘积。

自己的思路是对每一个高度从下往上扫描,对每一个高度利用分治的思想求得这个高度的最大连续长度(大于等于这个高度),可惜超时了,但是这种思想还是有用的,毕竟是之前书上看到的,虽然忘了……

分治思路:对于一个区间来说,最大连续长度在取区间左半部、右半部和中部的最大连续长度。

下面是我的代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
int n, len;
long long mx;
int hist[100005];
int hight[100005];
int search(int b, int e, int h) {
	if(b == e) return 1;
	int mid = b+(e-b)/2;
	int k, max, len = 0;
	int llen = search(b, mid, h);
	int rlen = search(mid+1, e, h);
	k = mid;
	while(hist[k--] >= h) len++;
	k = mid+1;
	while(hist[k++] >= h) len++;
	if(llen > rlen) max = llen;
	else max = rlen;
	return max>len?max:len;
}
int main() {
//	freopen("data.in", "r", stdin);
	int len1, len2;
	while(scanf("%d", &n) && n) {
		for(int i = 0; i < n; i++) {
			scanf("%d", &hist[i]);
			hight[i] = hist[i];
		}
		mx = -(1<<30);
		sort(hight, hight+n);
		len = unique(hight, hight+n)-hight;
		for(int i = 0; i < len; i++) {
			int ll = search(0, n, hight[i]);
			if(mx < hight[i]*ll) {
				mx = hight[i]*ll;
			}
		}
		printf("%d\n", mx);
	}
	return 0;
}
下面说一下最优代码的思路——单调队列!!!使用一个长度栈和高度栈记录这个高度的当前最长连续上升序列。 边输入边处理。实现上,长度栈存储高度栈相应位置当前的最大连续长度,每计算一次面积就会计算最大连续长度,然后更新长度。注意到,一旦遇到高度变低的情况,说明前面高度大于等于当前高度的部分全部失效——大于等于当前高度的只在当前高度面积的计算时有效,之后就不是连续的了。计算过程中会将前面大于等于这个高度的高度全部出栈,只留下小于当前高度的部分,只有这部分在后面的连续长度计算有效, 具体过程如下:

如果最新输入的高度比高度栈顶大的话,就进行压栈操作,并且把长度1压栈;否则的话,计算一次这个高度的当前最大面积,方法是不断的累加长度计算新的最大面积并进行出栈操作直到栈顶元素小于这个高度,最后将这个高度再次压栈,并且把当前将这个高度的对应当前最大连续长度也压入高度栈,保证高度栈和长度栈的一一对应关系。

最优代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
int stack[100010]={-2},len[100010];
long long ans;
int main() {
	int n,top,h;
	while(scanf("%d",&n), n) {
		top=0;ans=0;
		for(int i=0;i<=n;i++) { //注意是小于等n,相当于多循环一次 
			if(i<n)scanf("%d",&h);
			else h=-1; 			//这个-1是为了最后保证最后一个高度也会被计算 
			if(h > stack[top]) {
				stack[++top]=h;
				len[top]=1;
			} else {
				int l = 0;
				while(stack[top] >= h) {
					ans=max(ans,(long long)(l+len[top])*stack[top]);
					l += len[top--];	//累加最大连续长度 
				}
				stack[++top] = h;	//当前高度压栈 
				len[top] = l + 1;	//更新该高度最大连续长度 
			}
		}
		printf("%lld\n",ans); //使用long long类型以防面积溢出int类型 
	}
	return 0;
}



### 关于点云数据中的长方形处理 在三维目标检测领域,尤其是基于点云的目标检测任务中,矩形形状的物体(例如车辆、建筑物等)是一个常见的研究对象。论文《Voxel-FPN: multi-scale voxel feature aggregation in 3D object detection from point clouds》提出了多尺度体素特征聚合的方法来提升三维目标检测的效果[^1]。 #### 点云数据中的长方形样本表示 对于点云数据中的长方形容器或结构,通常采用边界框(Bounding Box)的形式进行描述。这种边界框可以分为两种形式: - **Axis-Aligned Bounding Box (AABB)**:边框轴对齐,即其边缘平行于坐标系的轴方向。 - **Oriented Bounding Box (OBB)**:允许旋转角度自由变化,能够更精确地拟合倾斜放置的对象。 这些边界框通过中心位置 `(cx, cy, cz)`、尺寸 `(w, l, h)` 和朝向角 `θ` 来定义,其中 `w`, `l`, `h` 分别代表宽度、长度和高度。 #### 数据预处理技术 为了有效提取点云中的长方形区域,在实际应用中有如下几种常见策略: 1. **体素化(Voxelization)** 将不规则分布的点云转换成固定大小的空间网格单元(voxels),从而便于后续卷积操作。这种方法有助于减少计算复杂度并增强模型鲁棒性。具体实现可参见 VoxelNet 中的相关设计思路。 2. **聚类(Clustering)** 使用 DBSCAN 或 Mean Shift 聚类算法将原始点集划分为若干子簇,再从中筛选满足特定几何约束条件的部分作为候选矩形实例。 3. **投影映射(Projective Mapping)** 把三维空间内的点投射到维平面(如 BEV-Bird's Eye View),利用传统图像分割手段识别潜在矩形轮廓后再反算回原域完成精确定位。 以下是 Python 实现的一个简单示例代码片段用于演示如何从鸟瞰图视角构建 AABB 边界框: ```python import numpy as np def create_aabb(points): """ 构造最小包围盒(Axis Aligned Bounding Box) 参数: points (numpy.ndarray): 输入点云数组 shape=(N, 3), N 表示点数 返回: dict: 包含 bbox 的参数 {'center':[], 'size':[]} """ min_coords = np.min(points[:, :2], axis=0) # XY 平面上的最小值 max_coords = np.max(points[:, :2], axis=0) # XY 平面上的最大值 center = (min_coords + max_coords)/2. size = max_coords - min_coords return {"center": list(center)+[np.mean(points[:, 2])], "size":list(size)+[points[:, 2].max()-points[:, 2].min()]} ``` 上述函数接受一组三维点作为输入,并返回对应 AABBox 的中心与尺寸信息。 #### 相关深度学习框架支持 目前主流开源库如 OpenPCDet 提供了完整的端到端解决方案,涵盖了前述提到的各种前处理模块以及网络架构搭建指南。开发者可以根据项目需求灵活选用合适的组件组合起来形成定制化的流水线作业流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值