C++ 算法学习——1.8 悬线法

1.问题引入:对于一个矩形图,图中放置着不少障碍,要求出最大的不含障碍的矩形。

2.分析:显然一个极大矩形是左右上下都被障碍挡住,无法再扩大的矩形,此时障碍也包括边界。

3.方法:悬线法考虑以当前点所在行为下界,以往上能达到的最大距离为高度,正上方所有点的往左最大距离的最小值和往右最大距离的最小值 之和作为宽的矩形。

其核心代码固定,使用时可以考虑直接套用。如下:

1.初始化求每个点leftmax,rightmax代码,0表示有障碍,不可走:

cpp 复制代码
void initialize(int** G, int** leftmax, int** rightmax, int n, int m) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (!G[i][j]) continue;
            leftmax[i][j] = leftmax[i][j - 1] + 1;
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = m; j >= 1; j--) {
            if (!G[i][j]) continue;
            rightmax[i][j] = rightmax[i][j + 1] + 1;
        }
    }
}

2.求最大矩形面积的代码:

cpp 复制代码
for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(i > 1 && G[i][j] && G[i-1][j]){
                upmax[i][j] = upmax[i-1][j] + 1;
                leftmax[i][j] = min(leftmax[i][j], leftmax[i-1][j]);//这样操作可以确保顺序遍历时,每个元素的leftmax都变为正上方元素的最小leftmax
                rightmax[i][j] = min(rightmax[i][j], rightmax[i-1][j]);//同理
            }
            ans = max(ans, (upmax[i][j] + 1) * (leftmax[i][j] + rightmax[i][j] - 1)); //高度+1(加上自身),宽度-1(因为往左包含了当前点,往右也包含了当前点,当前点算了两次)
        }
    }

P1. 洛谷p4147玉蟾宫

cpp 复制代码
#include<iostream>
#include<cmath>
using namespace std;
int n,m;

void initialize(int** G, int** leftmax, int** rightmax, int n, int m) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (!G[i][j]) continue;
            leftmax[i][j] = leftmax[i][j - 1] + 1;
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = m; j >= 1; j--) {
            if (!G[i][j]) continue;
            rightmax[i][j] = rightmax[i][j + 1] + 1;
        }
    }
}

void showcurmap(int** a)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        cout<<a[i][j]<<" ";
        cout<<endl;
    }
}

int main()
{
    cin>>n>>m;//考虑图置中,有效避免越界
    int** G;int**leftmax;int**rightmax;int** upmax;
    G=new int*[n+2];
    leftmax=new int*[n+2];
    rightmax=new int*[n+2];
    upmax=new int*[n+2];
    for(int i=0;i<=n+1;i++)
    {
        G[i]=new int[m+2]{0};
        leftmax[i]=new int[m+2]{0};
        rightmax[i]=new int[m+2]{0};
        upmax[i]=new int[m+2]{0};
    }

    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        char put;cin>>put;
        if(put=='F') G[i][j]=1;
    }
    initialize(G,leftmax,rightmax,n,m);
    long long ans=0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(i > 1 && G[i][j] && G[i-1][j]){
                upmax[i][j] = upmax[i-1][j] + 1;
                leftmax[i][j] = min(leftmax[i][j], leftmax[i-1][j]);//这样操作可以确保顺序遍历时,每个元素的leftmax都变为正上方元素的最小leftmax
                rightmax[i][j] = min(rightmax[i][j], rightmax[i-1][j]);//同理
            }
            ans = fmax(ans, (upmax[i][j] + 1) * (leftmax[i][j] + rightmax[i][j] - 1)); //高度+1(加上自身),宽度-1(因为往左包含了当前点,往右也包含了当前点,当前点算了两次)
        }
    }
    cout<<3*ans;
    //showcurmap(G);
}
相关推荐
守护者1702 分钟前
JAVA学习-练习试用Java实现“实现一个Hadoop程序,使用Hive进行复杂查询和数据筛查”
java·学习
吴梓穆33 分钟前
UE5学习笔记 FPS游戏制作35 使用.csv配置文件
笔记·学习·ue5
虾球xz35 分钟前
游戏引擎学习第199天
学习·游戏引擎
A林玖1 小时前
【计算机相关学习】R语言
开发语言·学习·r语言
浪淘沙jkp2 小时前
大模型学习三:DeepSeek R1蒸馏模型组ollama调用流程
学习·ollama·deepseek
nuo5342022 小时前
黑马 C++ 学习笔记
c语言·c++·笔记·学习
会讲英语的码农2 小时前
如何学习C++以及C++的宏观认知
开发语言·c++·学习
云上艺旅2 小时前
K8S学习之基础六十八:Rancher创建deployments资源
学习·云原生·容器·kubernetes·rancher
zhuyixiangyyds11 小时前
day21和day22学习Pandas库
笔记·学习·pandas
每次的天空11 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法