最大子矩阵
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#include #include #include #define N 1005using 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\n",sum); if(sum>mx) mx = sum; } } printf("%d\n",mx); } return 0;}