最大子矩阵
题目链接:最大子矩阵
题目描述:
给你一个 m×n 的整数矩阵,在上面找一个 x×y 的子矩阵,使子矩阵中所有元素的和最大。
输入描述:
输入数据的第一行为一个正整数 T,表示有 T 组测试数据。每一组测试数据的第一行为四个正整数 m,n,x,y(0<m,n<1000 AND 0<x<=m AND 0<y<=n),表示给定的矩形有 m 行 n 列。接下来这个矩阵,有 m 行,每行有 n 个不大于 1000 的正整数。
输出描述:
对于每组数据,输出一个整数,表示子矩阵的最大和。
输入样例:
1
4 5 2 2
3 361 649 676 588
992 762 156 993 169
662 34 638 89 543
525 165 254 809 280
输出样例:
2474
思路:
二位前缀和需要解决两点问题(例:f 数组为矩阵数组,v数组为前缀和数组):
- 如何计算得出前缀和数组 ?
v [ i ] [ k ] = f [ i ] [ k ] + v [ i − 1 ] [ k ] + v [ i ] [ k − 1 ] − v [ i − 1 ] [ k − 1 ] v[i][k] = f[i][k]+v[i-1][k]+v[i][k-1]-v[i-1][k-1] v[i][k]=f[i][k]+v[i−1][k]+v[i][k−1]−v[i−1][k−1]
注:i、k 分别为行循环变量和列循环变量。
- 如何计算子矩阵的前缀和(下式是求以矩阵坐标[i,k]为右下角元素的 x 行 y 列子矩阵前缀和)?
s u m = v [ i ] [ k ] − v [ i − x ] [ k ] − v [ i ] [ k − y ] + v [ i − x ] [ k − y ] sum=v[i][k]-v[i-x][k]-v[i][k-y]+v[i-x][k-y] sum=v[i][k]−v[i−x][k]−v[i][k−y]+v[i−x][k−y]
注:sum为 x 行 y 列的子矩阵的前缀和。
代码:
#include<stdio.h>
int f[1005][1005]; //用于存放矩阵元素
int v[1005][1005]; //用于存放前缀和
int main()
{
int s;
int m,n,x,y;
scanf("%d",&s);
while(s--)
{
scanf("%d %d %d %d",&m,&n,&x,&y);
for(int i=1;i<=m;i++)
for(int k=1;k<=n;k++)
scanf("%d",&f[i][k]);
//计算矩阵的前缀和
for(int i=1;i<=m;i++)
for(int k=1;k<=n;k++)
v[i][k]=f[i][k]+v[i-1][k]+v[i][k-1]-v[i-1][k-1]; //矩阵前缀和的公式
//计算子矩阵的和
int max=0;
for(int i=x;i<m;i++)
{
for(int k=y;k<n;k++)
if(max<(v[i][k]-v[i-x][k]-v[i][k-y]+v[i-x][k-y]))
max=v[i][k]-v[i-x][k]-v[i][k-y]+v[i-x][k-y];
}
printf("%d\n",max);
}
return 0;
}