首页 > 其他分享 >最大子矩阵和

最大子矩阵和

时间:2024-01-22 15:02:23浏览次数:20  
标签:right 最大 min int text 矩阵 maxN res

给定一个大矩阵,矩阵一般由 $0$ 或 $1$ 组成,要求你求出由 $0$ 或 $1$ 组成的最大子矩阵

做法颇多,先介绍一种做法,后续的单调栈,动态规划以及二维前缀和+二分再补充

 

P4147 玉蟾宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

把每个格子向上延伸的连续空格看成一条悬线,并用 $\text{up} (i, j)$、$\text{left} (i, j)$、$\text{right} (i, j)$ 表示格子 $(i, j)$ 的悬线长度以及该选线向左、向右运动的 “运动极限”。
每个格子 $(i, j)$ 对应着一个以 $i$ 行为下界、高度为 $\text{up} (i, j)$,左右边界分别为 $\text{left} (i, j)$ 和 $\text{right} (i, j)$ 的矩形。这些矩形中面积最大的就是题目所求。
当第 $i$ 行第 $j$ 列不是空格时,$3$ 个数组的值均为 $0$,否则 $\text{up} (i, j) = \text{up} (i - 1, j) + 1$,$\text{left} (i, j) = \max \{ \text{left} (i - 1, j), \text{lo} + 1 \}$。其中 $\text{lo}$ 是第 $i$ 行中,第 $j$ 列左边的最近障碍格的编号。$\text{right}$ 也可以同理计算,但需要从右往左计算,因为要维护第 $j$ 列右边最近的障碍格的列编号 $\text{ro}$。
时空复杂度均为 $\mathcal{O} (m n)$。下面另外两题与该方法同理

#include<bits/stdc++.h>
using namespace std;
const int N=2040;
int mp[N][N],l[N][N],r[N][N],h[N][N],n,m,res;
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            char c; cin>>c;
            if(c=='R') mp[i][j]=1;
            else h[i][j]=h[i-1][j]+1;
        }
    for(int i=1;i<=n;i++){
        int l_max=0,r_min=m+1;
        for(int j=1;j<=m;j++){
            if(mp[i][j]) l_max=j,l[i][j]=0;
            else l[i][j]=max(l[i-1][j],l_max+1);
        }
        for(int j=m;j>=1;j--){
            if(mp[i][j]) r_min=j,r[i][j]=m;
            else if(i==1) r[i][j]=r_min-1,res=max(res,h[i][j]*(r[i][j]-l[i][j]+1));
            else r[i][j]=min(r[i-1][j],r_min-1),res=max(res,h[i][j]*(r[i][j]-l[i][j]+1));
        }
    }
    cout<<res*3;
}

City Game - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <cstdio>
#include <algorithm>

const int maxN = 1000 + 10;

int K;
int M, N;
int city[maxN][maxN];

int up[maxN][maxN];
int left[maxN][maxN];
int right[maxN][maxN];

int main() {
    scanf("%d", &K);
    for (int kase = 1; kase <= K; kase++) {
        scanf("%d%d", &M, &N);
        for (int i = 1; i <= M; i++) for (int j = 1; j <= N; j++) {
            char ch;
            scanf(" %c", &ch);
            while (ch != 'F' && ch != 'R') scanf(" %c", &ch);
            if (ch == 'F') city[i][j] = 0;
            else city[i][j] = 1;
        }
        int ans = 0;
        for (int i = 1; i <= M; i++) {
            int lo = 0;
            int ro = N + 1;
            for (int j = 1; j <= N; j++) if (city[i][j]) {
                up[i][j] = 0;
                left[i][j] = 0;
                lo = j;
            } else if (i == 1) {
                up[i][j] = 1;
                left[i][j] = lo + 1;
            } else {
                up[i][j] = up[i - 1][j] + 1;
                left[i][j] = std::max(left[i - 1][j], lo + 1);
            }
            for (int j = N; j >= 1; j--) if (city[i][j]) {
                right[i][j] = N;
                ro = j;
            } else if (i == 1) {
                right[i][j] = ro - 1;
                ans = std::max(ans, up[i][j] * (right[i][j] - left[i][j] + 1));
            } else {
                right[i][j] = std::min(right[i - 1][j], ro - 1);
                ans = std::max(ans, up[i][j] * (right[i][j] - left[i][j] + 1));
            }
        }
        printf("%d\n", ans * 3);
    }
    return 0;
}

P5943 [POI2002] 最大的园地 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int n,m,mp[N][N],h[N][N],r[N][N],l[N][N],res;
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) cin>>mp[i][j];
    for(int i=1;i<=n;i++){
        int l_max=0,r_min=n+1;
        for(int j=1;j<=n;j++){
            if(mp[i][j]) l_max=j,l[i][j]=0,h[i][j]=0;
            else if(i==1) h[i][j]=1,l[i][j]=l_max+1;
            else h[i][j]=h[i-1][j]+1,l[i][j]=max(l[i-1][j],l_max+1);
        }
        for(int j=n;j>=1;j--){
            if(mp[i][j]) r_min=j,r[i][j]=n;
            else if(i==1) r[i][j]=r_min-1,res=max(res,h[i][j]*(r[i][j]-l[i][j]+1));
            else r[i][j]=min(r[i-1][j],r_min-1),res=max(res,h[i][j]*(r[i][j]-l[i][j]+1));
        }
    }
    cout<<res;
}

 

标签:right,最大,min,int,text,矩阵,maxN,res
From: https://www.cnblogs.com/o-Sakurajimamai-o/p/17980048

相关文章

  • 每日一题 2024-1-22 最大交换
    1.题目(中等)原题链接给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。示例1:输入:2736输出:7236解释:交换数字2和数字7。示例2:输入:9973输出:9973解释:不需要交换。注意:给定数字的范围是\([0,10^8]\)2.解题思路贪心,......
  • 每日一题 2024-1-21 分割数组的最大值
    1.题目(困难)原题链接给定一个非负整数数组\(nums\)和一个整数\(k\),你需要将这个数组分成\(k\)个非空的连续子数组。设计一个算法使得这\(k\)个子数组各自和的最大值最小。示例1:输入:nums=[7,2,5,10,8],k=2输出:18解释:一共有四种方法将nums分割为2个子数组......
  • 矩阵代数的 Burnside 定理
    我们详细重述并证明[1,Sec.1.2]中的Burnside定理及其相关推论.下面设V是复数域C上的有限维线性空间,B(V)是V上的线性变换代数;I是B(V)的单位元.Burnside定理证明较长.为使逻辑顺畅,先做一些准备工作.Lemma1设A是B(V)上的乘法半群,若A不可约,则对任意非零的x......
  • 3.2 最大似然估计
    一种给定观测数据来评估模型参数的方法,即模型和数据已知参数未定。似然性:在观测结果已知的情况下,对参数进行估值和猜测,即代表某个参数为特定值的可能性。似然性=L(参数|数据)=L(θ|x)参数θ数据x步骤:1、确定分布类型2、尝试不同的参数值,找到似然性最大的。......
  • MySQL连接池最大连接数设置
    默认连接数的选择应该基于你的应用程序的需求以及数据库服务器的性能和配置。 对于大多数小型和中型应用程序来说,10个连接可能是一个合理的起点。然而,如果你的应用程序具有较高的并发性或处理大量数据库操作,你可能需要增加连接数。否则,在高负载时,连接池中的连接可能会快速耗尽......
  • stm32笔记[13]-矩阵键盘
    摘要在蓝桥杯物联网的CT127C开发板上测试矩阵键盘模块;复用矩阵键盘的io口和i2c3的io口;在屏幕显示按下的按键.开发环境Keil5.35.00HAL库版本:STM32CubeFW_L0V1.12.0STM32CubeMX:6.2.1原理简介stm32的引脚复用voidHAL_I2C_MspDeInit(I2C_HandleTypeDef*i2cHandle)......
  • OpenCV仿射变换+投射变换+单应性矩阵
    OpenCV仿射变换+投射变换+单应性矩阵本来想用单应性求解小规模运动的物体的位移,但是后来发现即使是很微小的位移也会带来超级大的误差甚至错误求解,看起来这个方法各种行不通,还是要匹配知道深度了以后才能从三维仿射变换来入手了,纠结~estimateRigidTransform():计算多个二维......
  • 最大异或和 可持久化数据结构入门
    最大异或和题目描述给定一个非负整数序列\(\{a\}\),初始长度为\(N\)。有\(M\)个操作,有以下两种操作类型:Ax:添加操作,表示在序列末尾添加一个数\(x\),序列的长度\(N\)加\(1\)。Qlrx:询问操作,你需要找到一个位置\(p\),满足\(l\lep\ler\),使得:\(a[p]\oplusa[p+1]......
  • 基于矩阵分解的协同过滤算法
    引言随着互联网、大数据等新技术的迅速发展,人们的生活变得更加便捷,但同时也导致网络数据爆炸式增长。为了快速帮助用户找到感兴趣的内容,越来越多的研究者致力于推荐算法的研究,以提高推荐质量,向用户推荐更符合其喜好的内容。然而,目前的推荐算法仍存在数据稀疏性、隐私保护和冷启动......
  • 机器学习-概率图模型系列-最大熵马尔科夫模型-38
    目录MaxEntropyMarkovModelMEMM,即最大熵马尔科夫模型,属于判别式模型。最大熵模型+隐马尔可夫模型HMMM没办法加入新的特征,MEMM是判别式模型,这就允许它可以加入更多的Features。观测独立假设对应的就是朴素贝叶斯的条件独立性假设,即t+1时刻的y状态只与t时刻的y状态有关系......