最大子矩阵
Time Limit: 30000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3906 Accepted Submission(s): 1994
Problem Description
给你一个m×n的整数矩阵,在上面找一个x×y的子矩阵,使子矩阵中所有元素的和最大。
Input
输
入数据的第一行为一个正整数T,表示有T组测试数据。每一组测试数据的第一行为四个正整数m,n,x,y(0<m,n<1000 AND
0<x<=m AND
0<y<=n),表示给定的矩形有m行n列。接下来这个矩阵,有m行,每行有n个不大于1000的正整数。
Output
对于每组数据,输出一个整数,表示子矩阵的最大和。
Sample Input
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
Sample Output
2474
Author
lwg
Source
很多方法,二维树状数组,DP,二维RMQ。。。数据很水,二维树状数组491MS,有时间在补二维RMQ,dp解法
#include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> #define N 1005 using namespace std; int C[N][N]; int n,m,x,y; int lowbit(int x1){ return x1&(-x1); } int update(int x1,int y1,int value){ for(int i=x1;i<=n;i+=lowbit(i)){ for(int j=y1;j<=m;j+=lowbit(j)){ C[i][j]+=value; } } } int getSum(int x1,int y1){ int value = 0; for(int i=x1;i>=1;i-=lowbit(i)){ for(int j=y1;j>=1;j-=lowbit(j)){ value+=C[i][j]; } } return value; } int main() { int tcase; scanf("%d",&tcase); while(tcase--){ memset(C,0,sizeof(C)); scanf("%d%d%d%d",&n,&m,&x,&y); int num; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&num); update(i,j,num); } } int mx = -1; for(int i=1;i<=n;i++){ if(i+x-1>n) continue; for(int j=1;j<=m;j++){ if(j+y-1>m) continue; int x1 = i; int x2 = i+x-1; int y1 = j; int y2 = j+y-1; int sum = getSum(x2,y2)-getSum(x1-1,y2)-getSum(x2,y1-1)+getSum(x1-1,y1-1); //printf("%d ",sum); if(sum>mx) mx = sum; } } printf("%d ",mx); } return 0; }