题目:在一个矩阵中,寻找一个元素加和最大的子矩阵。
分析:简单题、暴力枚举。如果直接暴力时间复杂度为O (t*n^2*d^2),所以要利用dp做预处理。矩形用左上和右下两个顶点描述,即{(x1,y1),(x2,y2)}。设f(i,j)为矩形{(0,0),(i,j)}的元素之和,则矩形{(x1,y1),(x2,y2)}的元素和为f(x2,y2)-f(x1,y2)-f(x2,y1)+f(x1,y1)。时间复杂度为O(t*n^2)。
注意:枚举的范围是 [0,max_x] 和 [0,max_y]。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int rat[ 1030 ][ 1030 ];
int sum[ 1030 ][ 1030 ];
int main()
{
int t,d,n,x,y,r;
while ( scanf("%d",&t) != EOF )
while ( t -- ) {
scanf("%d%d",&d,&n);
memset( rat, 0, sizeof( rat ) );
int min_x = 1025,max_x = 1;
int min_y = 1025,max_y = 1;
for ( int i = 0 ; i < n ; ++ i ) {
scanf("%d%d%d",&x,&y,&r);
++ x; ++ y;//范围[1,1025])
rat[ x ][ y ] = r;
if ( x < min_x ) min_x = x;
if ( x > max_x ) max_x = x;
if ( y < min_y ) min_y = y;
if ( y > max_y ) max_y = y;
}
//预处理
memset( sum, 0, sizeof( sum ) );
for ( int i = min_x ; i <= max_x ; ++ i ) {
int sum_y = 0;
for ( int j = min_y ; j <= max_y ; ++ j ) {
sum_y += rat[ i ][ j ];
sum[ i ][ j ] = sum_y;
if ( i > min_x )
sum[ i ][ j ] += sum[ i-1 ][ j ];
}
}
int max = 0;
int xxx = 0;
int yyy = 0;
for ( int i = 0 ; i <= max_x ; ++ i )
for ( int j = 0 ; j <= max_y ; ++ j ) {
int lu_x = i-d-1,rd_x = i+d;
int lu_y = j-d-1,rd_y = j+d;
if ( lu_x < 0 ) lu_x = 0;
if ( lu_y < 0 ) lu_y = 0;
if ( rd_x > max_x ) rd_x = max_x;
if ( rd_y > max_y ) rd_y = max_y;
int now = sum[ rd_x ][ rd_y ]
- sum[ rd_x ][ lu_y ]
- sum[ lu_x ][ rd_y ]
+ sum[ lu_x ][ lu_y ];
if ( max < now ) {
max = now;
xxx = i-1;
yyy = j-1;
}
}
printf("%d %d %d\n",xxx,yyy,max);
}
return 0;
}