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);
}
相关推荐
数据与后端架构提升之路32 分钟前
从神经元到神经网络:深度学习的进化之旅
人工智能·神经网络·学习
一行141 分钟前
电脑蓝屏debug学习
学习·电脑
星LZX1 小时前
WireShark入门学习笔记
笔记·学习·wireshark
阑梦清川1 小时前
在鱼皮的模拟面试里面学习有感
学习·面试·职场和发展
qq_433099401 小时前
Isaac Gym学习笔记——概述
学习
秃头佛爷3 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
dayouziei5 小时前
java的类加载机制的学习
java·学习
dsywws8 小时前
Linux学习笔记之vim入门
linux·笔记·学习
晨曦_子画9 小时前
3种最难学习和最容易学习的 3 种编程语言
学习
城南vision9 小时前
Docker学习—Docker核心概念总结
java·学习·docker