蓝桥杯上面的题目这题说的是 给了 一个n*m的矩阵 然后取其中的 k*k 大小的面积出来 计算这样取出的三块的最大可以采油的大小最大 将一个矩形区域分成 三块有 6种切法 1上 中下,2 左中右 3 左右下 4 左上下 5 右上下 6 上 左右 然后处理好每个区域所能取到的值 然后 枚举两条线 得到 三个区域 计算最大值 在上中下 左中右 的情况是枚举中间区域是K宽度的 地方 调试了好久
#include <cstdio> #include <string.h> #include <iostream> using namespace std; const int maxn = 1505; struct oil{ int up_Right[maxn][maxn],up_Left[maxn][maxn],down_Right[maxn][maxn],down_Left[maxn][maxn]; int map[maxn][maxn],row[maxn][maxn],column[maxn][maxn],N,M,K; int valu_column[maxn],valu_row[maxn],ans; int maxv(int a,int b){ return a>b?a:b; } void read(){ scanf("%d%d%d",&N,&M,&K); memset(row,0,sizeof(row)); memset(column,0,sizeof(column)); memset(up_Left,0,sizeof(up_Left)); memset(up_Right,0,sizeof(up_Right)); memset(down_Right,0,sizeof(down_Right)); memset(down_Left,0,sizeof(down_Left)); memset(valu_row,0,sizeof(valu_row)); memset(valu_column,0,sizeof(valu_column)); for( int i = 1 ; i <= N ; ++ i ) for( int j = 1 ;j <= M ; ++ j ) scanf("%d",&map[i][j]); for( int i = 1; i <= N ;i++ ) for( int j=1; j <= M ; ++ j){ row[i][j] = row[i][j-1] + map[i][j]; column[i][j] = column[i-1][j] + map[i][j] ; } } void prepare(){ for(int i = K ; i <= N ; ++ i){ int sum = 0; for( int j = 1; j <=K ; j++ ) sum+=column[i][j]-column[i-K][j]; up_Left[i][K]=maxv(sum,up_Left[i-1][K]); valu_row[i] = sum; for( int j = K+1 ; j <= M ; j ++ ){ sum=sum-(column[ i ][ j - K ]-column[ i - K ][ j - K ])+column[i][j]-column[i-K][j]; valu_row[i] = maxv(sum,valu_row[i]); up_Left[i][j]=maxv(maxv(sum,up_Left[i][j-1]),up_Left[i-1][j]); } } for( int i=K ; i <= N ; ++ i ){ int sum = 0 ; for( int j=M ; j>M-K ; -- j ) sum += column[i][j]-column[i-K][j]; up_Right[i][M-K+1]=maxv(up_Right[i-1][M-K+1],sum); for( int j=M-K ; j>0 ; -- j){ sum = sum - (column[i][j+K]-column[i-K][j+K])+column[i][j]-column[i-K][j]; up_Right[i][j] = maxv( up_Right[i-1][j],maxv(up_Right[i][j+1],sum)); } } for( int j = K ; j <= M ; ++ j){ int sum = 0; for(int i=N ; i > N - K ; -- i) sum += row[i][j]-row[i][j-K]; down_Left[N-K+1][j]=maxv(down_Left[N-K+1][j-1],sum); valu_column[j]=sum; for( int i = N- K ; i>0 ; -- i){ sum = sum -( row[i+K][j]-row[i+K][j-K])+row[i][j]-row[i][j-K]; valu_column[j]=maxv(valu_column[j],sum); down_Left[i][j] = maxv(down_Left[i+1][j],maxv(sum,down_Left[i][j-1])); } } for( int j=M-K+1; j > 0 ; -- j ){ int sum = 0; for(int i= N ; i > N - K ; -- i) sum += row[i][j+K-1]-row[i][j-1]; down_Right[N-K+1][j]=maxv(sum,down_Right[N-K+1][j+1]); for( int i = N-K ; i > 0 ; -- i){ sum=sum -(row[i+K][j+K-1]-row[i+K][j-1]) + row[i][j+K-1] - row[i][j-1]; down_Right[i][j]=maxv(down_Right[i+1][j],maxv(sum,down_Right[i][j+1])); } } } void solve(){ ans =0; for( int i=K ; i <= N-K*2; i++ ) ans = maxv( ans , up_Left[i][M]+valu_row[i+K]+down_Right[i+K+1][1]); for( int i = K ;i <= M- K*2 ; i++) ans =maxv(ans, up_Left[N][i]+valu_column[i+K]+up_Right[N][i+K+1]); for( int i=K; i<=N-K; i++) for( int j = K ;j <= M-K ;++ j){ ans=maxv(ans,up_Left[i][j]+up_Right[i][j+1]+down_Left[i+1][M]); ans=maxv(ans,up_Left[N][j]+up_Right[i][j+1]+down_Right[i+1][j+1]); ans=maxv(ans,up_Left[i][j]+up_Right[N][j+1]+down_Left[i+1][j]); ans=maxv(ans,up_Left[i][M]+down_Left[i+1][j]+down_Right[i+1][j+1]); } } }T; int main(){ T.read(); T.prepare(); T.solve(); printf("%d ",T.ans); return 0; }