【DP】吃西瓜

xiaoxiao2021-07-27  104

【题目描述】

此题中出现的所有数全为整数 SubRaY有一天得到一块西瓜,是长方体形的.... SubRaY发现这块西瓜长m厘米,宽n厘米,高h厘米.他发现如果把这块西瓜平均地分成m*n*h块1立方厘米的小正方体,那么每一小块都会有一个营养值(可能为负,因为西瓜是有可能坏掉的,但是绝对值不超过200). 现在SubRaY决定从这m*n*h立方厘米的西瓜中切出mm*nn*hh立方厘米的一块小西瓜(一定是立方体形,长宽高均为整数),然后吃掉它.他想知道他最多能获得多少营养值.(0<=mm<=m,0<=nn<=n,0<=hh<=h.mm,nn,hh的值由您来决定). 换句话说,我们希望从一个m*n*h的三维矩阵中,找出一个三维子矩阵,这个子矩阵的权和最大.

【输入格式】

首行三个数h,m,n(注意顺序),分别表示西瓜的高,长,宽.以下h部分,每部分是一个m*n的矩阵,第i部分第j行的第k个数表示西瓜第i层,第j行第k列的那块1立方厘米的小正方体的营养值.

【输出格式】

SubRaY所能得到的最大营养值


三维的最大子长方体问题,先将三维图形枚举上下层数转换为平面最大最大子矩阵,再将平面枚举上下行转化为求最大子段和

#include<iostream> #include<iomanip> #include<cstring> #include<cstdio> using namespace std; int n,h,m,a[34][55][55],sum[34][55][55],f[55],b[55][55],ans,dp[55]; int ask() { int maxx=0; memset(dp,0,sizeof(dp)); maxx=f[1],dp[1]=f[1]; for(int i=2;i<=m;i++) { dp[i]=max(dp[i-1]+f[i],f[i]); if(dp[i]>maxx) maxx=dp[i]; } return maxx; } int dps() { int maxx=0; for(int i=1;i<=n;i++) { memset(f,0,sizeof(f)); for(int j=i;j<=n;j++) { for(int k=1;k<=m;k++) f[k]+=b[j][k]; int sum=ask(); if(sum>maxx) maxx=sum; } } return maxx; } int main() { scanf("%d%d%d",&h,&n,&m); for(int i=1;i<=h;i++) for(int j=1;j<=n;j++) for(int k=1;k<=m;k++) scanf("%d",&a[i][j][k]),sum[i][j][k]=sum[i-1][j][k]+a[i][j][k]; for(int i=1;i<=h;i++) { for(int j=i;j<=h;j++) { for(int up=1;up<=n;up++) { for(int down=1;down<=m;down++) { b[up][down]=sum[j][up][down]-sum[i-1][up][down]; } } int maxx=dps(); if(maxx>ans) ans=maxx; } } printf("%d",ans); }

 

转载请注明原文地址: https://www.6miu.com/read-4823355.html

最新回复(0)