最大子阵列和

本文介绍了一种基于动态规划的方法来解决最大子矩阵和的问题。通过枚举矩阵的上下边界并利用部分和矩阵来实现O(1)的时间复杂度获取同一列元素的和,进而转化为一维数组最大子数组和问题求解。

hoj2558,给定一个矩阵,返回最大子矩阵和。

思考(动态规划):

1.读取的同时和矩阵运算部的矩阵

2.枚举矩阵的行上下边界,固定的上,下边界线之后。

按照部分和矩阵O(1)得到同一列元素的和,转化为1维数组的情况

3.依照一维数组的情况,求最大子数组和的思路是:

能够从后往前计算,每次先算以当前元素A[i]为开头的最大和start

再将start与当前A[i+1:n]所代表的真实最大和进行比較,作为A[i:n]的真实最大和保存起来。

4.输出遍历过程中得到的最大值MAX就可以

cpp代码:

#include<iostream>
#define SIZE 102
#define INF 1000
using namespace std;
int maxx(int a,int b){
    return a>b?

a:b; } int main(){ int n,i,j,k,a,c,tmp,MAX,start,all; int num[SIZE]; int mat[SIZE][SIZE]; while(cin>>n){ //读入矩阵的同一时候计算部分和矩阵 for(j=0;j<=n;j++)mat[0][j]=mat[j][0]=0; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ cin>>mat[i][j]; mat[i][j]+=mat[i-1][j];//累积部分和 } } //開始处理 MAX=-INF; for(a=1;a<=n;a++){ for(c=a;c<=n;c++){//枚举上下边界 start=mat[c][n]-mat[a-1][n]; all=start;//先给数组最后一个元素赋值 for(k=n-1;k>=1;k--){//从后往前计算 tmp=mat[c][k]-mat[a-1][k];//依据部分和算出当前元素值 start=maxx(tmp+start,tmp);//先比較以tmp开头的 all=maxx(start,all);//再比較总的 } if(all>MAX)MAX=all; } } cout<<MAX<<endl; } return 0; }



版权声明:本文博主原创文章,博客,未经同意不得转载。

假设有一个 $n \times m$ 的矩阵 $A$,我们要求出其中最大的邻接阵列。 首先,我们需要定义什么是邻接阵列。一个邻接阵列是指在矩阵 $A$ 中,选取一列 $j$,并在这一列上选出一段连续的行 $i_1, i_2, \dots, i_k$,那么这段行列 $j$ 形成的矩阵就是一个邻接阵列。 接下来,我们考虑使用分归算法来解决这个问题。我们可以将矩阵 $A$ 分成左右两个部分,分别求出左右两个部分的最大邻接阵列。然后,我们还需要考虑跨越左右两个部分的邻接阵列,也就是说,我们需要找到包含左右两个部分的邻接阵列,求出这个邻接阵列。 具体来说,我们可以从中间列开始,向左右两个方向扩展,记录下左边一段的最大阵列 $L$ 右边一段的最大阵列 $R$,以及跨越中间列的最大邻接阵列 $M$。那么,整个矩阵的最大邻接阵列就是 $L, R, M$ 中的最大值。 接下来,我们考虑如何求出跨越中间列的最大邻接阵列 $M$。我们可以从中间列开始,向上下两个方向扩展,记录下上边一段的最大阵列 $U$ 下边一段的最大阵列 $D$,以及跨越中间列的邻接阵列 $M'$。那么,跨越中间列的最大邻接阵列 $M$ 就是 $U + D - A_{mid}$,其中 $A_{mid}$ 是中间列的。 最后,我们可以用分归算法求解整个问题。具体来说,我们可以递归地求解左右两个部分的最大邻接阵列,然后再求出跨越左右两个部分的邻接阵列,最后返回三者的最大值即可。 时间复杂度为 $O(nm \log m)$,因为我们需要递归 $\log m$ 层。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值