题目:吃西瓜

题目描述

[说明]此题中出现的所有数全为整数
[背景]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的三维矩阵中,找出一个三维子矩阵,这个子矩阵的权和最大.

一个2*3*4的例子,最优方案为切红色2*3*1部分
[数据范围]
对于30%的数据,h=1,1<=m,n<=10
对于全部的数据,1<=h<=32,1<=m,n<=50,保证h<=m,n

输入格式

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

输出格式

SubRaY所能得到的最大营养值

 

 

 

题解:

动态规划,这道题很不错,叫我们求的是最大加权三维矩阵。第一次做此类题目,学习可知最大加权三维矩阵可以通过优化最大加权二维矩阵算法快速获得,算法时间复杂度是O(n^5)。而最大加权二维矩阵又可通过最大加权线的算法优化得到。出乎我意料的是,在做完这道题的第二天,我就做到了求最大加权二维矩阵的题目,在第三天,我又做到了求最大加权线的题。也许能使我悟出一些道理。

代码实现:

#include<iostream>
#include<cstring>
using namespace std;

int main()
{
    int f[33][51][51]={0},h,m,n,i,j,k;
    cin>>h>>m>>n;
    
    for(i=1;i<=h;i++)
    for(j=1;j<=m;j++)
    for(k=1;k<=n;k++)
    cin>>f[i][j][k];
    
    for(i=1;i<=h;i++)
    for(j=1;j<=m;j++)
    for(k=1;k<=n;k++)
    f[i][j][k]+=f[i-1][j][k];
    
    for(i=1;i<=h;i++)
    for(j=1;j<=m;j++)
    for(k=1;k<=n;k++)
    f[i][j][k]+=f[i][j-1][k];
    
    int h1,m2;int c[51],p[51],ans=0;
    for(i=1;i<=h;i++)
    for(h1=1;h1<=i;h1++)
    for(j=1;j<=m;j++)
    for(m2=1;m2<=j;m2++)
    {
     memset(c,0,sizeof(c));
     memset(p,0,sizeof(p));
     for(k=1;k<=n;k++){
                       p[k]+=f[i][j][k]-f[h1-1][j][k]-f[i][m2-1][k]+f[h1-1][m2-1][k];
                       c[k]=max(p[k]+c[k-1],p[k]);
                       if(c[k]>ans) ans=c[k];                     
                       }    
                        }
                        
     cout<<ans<<endl;
     return 0;
    
    }
posted on 2012-01-16 23:07  怡红公子  阅读(527)  评论(2编辑  收藏  举报