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);
}
相关推荐
程序员大金2 分钟前
基于SpringBoot+Vue+MySQL的在线学习交流平台
java·vue.js·spring boot·后端·学习·mysql·intellij-idea
码到成龚7 分钟前
《数字图像处理基础》学习01-数字图像处理的相关基础知识
学习
程序员小李_1 小时前
心理——《在绝望中寻找希望:俞敏洪写给迷茫不安的年轻人》
学习
向上的车轮1 小时前
Django学习笔记四:urls配置详解
笔记·学习·django
新手unity自用笔记1 小时前
项目-坦克大战学习笔记-按键按下控制方向
笔记·学习·c#
瞌睡不来2 小时前
(刷题记录5)盛最多水的容器
c++·笔记·学习·题目记录
一 乐2 小时前
考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)
java·数据库·学习·考研·微信·小程序·源码
朝九晚五ฺ3 小时前
【Linux探索学习】第三弹——Linux的基础指令(下)——开启新篇章的大门
linux·运维·学习
IM_DALLA3 小时前
【Verilog学习日常】—牛客网刷题—Verilog企业真题—VL74
学习·fpga开发·verilog学习