最大子矩阵和
2016-02-13 13:49
169 查看
问:给定一个N*M的矩阵,其子矩阵有N*M*N*M个子矩阵,将子矩阵中的每个元素求和,求和最大的子矩阵。
我们可以枚举每个子矩阵,时间复杂度为0(N*M*N*M),代码如下:
不过我们可以优化到o(N2*M)我们之前遇到过一个一维数组中最大子段和的问题。其状态转移方程为 if(b[i-1]>0) b[i]=b[i-1]+a[i] else b[i]=a[i],
其时间复杂度为0(N),代码如下:
我们可以这样想:我们任意取第i行到第j行列全包含的子矩阵。我们将每行求和,转化为求最大子段和问题。我们就可以在O(M)的时间内枚举M*(M+1)/2个子矩阵,而这样的列全包含矩阵有
N*(N+1)/2 个。这样我们就可以在O(N*N*M)的时间内求得,这样大大降低了时间复杂度。
完整代码如下:
我们可以枚举每个子矩阵,时间复杂度为0(N*M*N*M),代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=105; int mat[MAXN][MAXN]; int sum[MAXN][MAXN]; int n; int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&mat[i][j]); sum[1][1]=mat[1][1]; for(int i=2;i<=n;i++) sum[1][i]=sum[1][i-1]+mat[1][i]; for(int i=2;i<=n;i++) sum[i][1]=sum[i-1][1]+mat[i][1]; for(int i=2;i<=n;i++) for(int j=2;j<=n;j++) { sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+mat[i][j];//sum[i][j]表示左上角为mat[1][1],右下角为mat[i][j]所表示的矩阵之和 } int res=-10000000; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int x=i;x<=n;x++) for(int y=j;y<=n;y++) { int total=sum[x][y]-sum[x][j-1]-sum[i-1][y]+sum[i-1][j-1]; if(total>res) res=total; } printf("%d\n",res); } return 0; }
不过我们可以优化到o(N2*M)我们之前遇到过一个一维数组中最大子段和的问题。其状态转移方程为 if(b[i-1]>0) b[i]=b[i-1]+a[i] else b[i]=a[i],
其时间复杂度为0(N),代码如下:
int MaxSubSegSum(int num[]) { int b[MAXN],maxn; maxn=b[0]=num[0]; for(int i=1;i<m;i++) { if(b[i-1]>0) b[i]=b[i-1]+num[i]; else b[i]=num[i]; maxn=max(maxn,b[i]); } return maxn; }
我们可以这样想:我们任意取第i行到第j行列全包含的子矩阵。我们将每行求和,转化为求最大子段和问题。我们就可以在O(M)的时间内枚举M*(M+1)/2个子矩阵,而这样的列全包含矩阵有
N*(N+1)/2 个。这样我们就可以在O(N*N*M)的时间内求得,这样大大降低了时间复杂度。
完整代码如下:
#include"cstdio" #include"cstring" #include"algorithm" using namespace std; const int MAXN=1005; int n,m; int matrix[MAXN][MAXN]; int l,r,up,down; int ll,rr; int lll,rrr; int MaxSubSegSum(int num[]) { int b[MAXN],maxn; maxn=b[0]=num[0]; l=r=0; for(int i=1;i<m;i++) { if(b[i-1]>0) { b[i]=b[i-1]+num[i]; r=i; } else { b[i]=num[i]; r=i; l=i; } if(maxn<b[i]) { maxn=b[i]; ll=l; rr=r; } } return maxn; } int total[MAXN][MAXN]; int MaxSubMat() { for(int j=0;j<m;j++) total[0][j]=matrix[0][j]; for(int i=1;i<n;i++) for(int j=0;j<m;j++) { total[i][j]=matrix[i][j]; total[i][j]+=total[i-1][j]; } int maxn=-0x3fffffff; int temp[MAXN]; for(int i=0;i<n;i++) { for(int j=i;j<n;j++) { for(int z=0;z<m;z++) { if(i==0) temp[z]=total[j][z]; else temp[z]=total[j][z]-total[i-1][z]; } if(MaxSubSegSum(temp)>maxn) { maxn=MaxSubSegSum(temp); up=i; down=j; lll=ll; rrr=rr; } } } return maxn; } int main() { scanf("%d%d",&m,&n); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&matrix[i][j]); int ans=MaxSubMat(); printf(" 最大子矩阵为:\n"); for(int i=up;i<=down;i++) { for(int j=lll;j<=rrr;j++) printf("%d ",matrix[i][j]); printf("\n"); } printf("其和为:%d\n",ans); return 0; } /* 3 3 -1 3 -1 2 -1 3 -3 1 2 3 -1 -1 3 1 2 7 */
相关文章推荐
- 学习android前配置
- ObQueryNameString routine
- 菜单
- POJ 2536 Gopher II(二分图最大匹配)
- H5的拖曳效果示例
- Shiro教程
- RDO Stack Exception: UnboundLocalError: local variable 'logFile' referenced before assignment
- Python 元组 集合
- RDO Stack Exception: UnboundLocalError: local variable 'logFile' referenced before assignment
- 我眼中的艺术
- ANDROID_MARS学习笔记_S01原始版_003_对话框
- uva10340 -All in All
- 东汉十三州以及各个郡的说明
- 穷人思维是人生第一大毒瘤
- uva10970- Big Chocolate
- ld script 命令摘录
- 代理模式
- 多种语言实现Base64编码解码
- 二维码生成工具类
- 博客搬家 -> www.wilkeryun.com