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);
}
相关推荐
AI完全体1 分钟前
【AI日记】24.11.22 学习谷歌数据分析初级课程-第2/3课
学习·数据分析
Mephisto.java37 分钟前
【大数据学习 | Spark-Core】Spark提交及运行流程
大数据·学习·spark
PandaCave1 小时前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
yuwinter1 小时前
鸿蒙HarmonyOS学习笔记(2)
笔记·学习·harmonyos
red_redemption1 小时前
自由学习记录(23)
学习·unity·lua·ab包
幽兰的天空2 小时前
默语博主的推荐:探索技术世界的旅程
学习·程序人生·生活·美食·交友·美女·帅哥
沐泽Mu3 小时前
嵌入式学习-C嘎嘎-Day05
开发语言·c++·学习
你可以叫我仔哥呀3 小时前
ElasticSearch学习笔记三:基础操作(一)
笔记·学习·elasticsearch
脸ル粉嘟嘟3 小时前
GitLab使用操作v1.0
学习·gitlab
路有瑶台3 小时前
MySQL数据库学习(持续更新ing)
数据库·学习·mysql