zoukankan      html  css  js  c++  java
  • [Swust OJ 589]--吃西瓜(三维矩阵压缩)

    题目链接:http://acm.swust.edu.cn/problem/589/

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

     
    Input
    首行三个数h,m,n(注意顺序),分别表示西瓜的高,长,宽. 
    以下h部分,每部分是一个m*n的矩阵,第i部分第j行的第k个数表示西瓜第i层,第j行第k列的那块1立方厘米的小正方体的营养值. 
    1 <= h <= 32,1 <= m,n <= 50,保证h <= m,n
     
    Output
    Wraith所能得到的最大营养值
     
    Sample Input
    2 3 4
    4 1 2 8
    0 5 -48 4
    3 0 1 9
    2 1 4 9
    1 0 1 7
    3 1 2 8

    Sample Output
    45


    解题思路:

    这一题,求一个最大长方体,就需要将长方体压缩成矩阵,再压缩成线,总体是三维的,时间效率T(n)=O(n5)
    最大加权矩形我们用sum[i][j]表示前 i 行的第 j 列的和,这里我们可以以此类推,用sum[i][j][k]表示前 i 层、前 j 行的第 k 列的和,
    这里在放一下图具体说明一下
    那么sum[i][j][k] = sum[i][j - 1][k] + sum[i][j][k - 1] - sum[i][j - 1][k - 1] + x[i][j][k],自己可以模拟一下
    然后我们就枚举行(上界sx 和 下界ex),枚举列(上界sy 和下界ey),再枚举高h
    现在就需要把他们压缩了,把他们压缩出来记为ptr,用下图来说明(图在网上找的,有点问题,可以自己用画图画来看看,汗~~~)
    ptr=sum[i][ex][ey] - sum[i][sx - 1][ey] - sum[i][ex][sy - 1] + sum[i][sx - 1][sy - 1];
    然后就变成线性的问题了Orz~~~
     
    代码如下:
     1 #include <iostream>
     2 #include <algorithm>
     3 using namespace std;
     4 #define maxn 51
     5 #define inf 0x3f3f3f3f
     6 int h, m, n, ans;
     7 int sum[maxn][maxn][maxn], x[maxn][maxn][maxn], dp[maxn][maxn][maxn][maxn];
     8 //sum前h层,前i行,第j列的权值之和,dp数组三维压缩成二维后sx,sy点到ex,ey点构成平面矩形最值
     9 
    10 int main(){
    11     cin >> h >> m >> n;
    12     for (int i = 1; i <= h; i++)
    13     for (int j = 1; j <= m; j++)
    14     for (int k = 1; k <= n; k++){
    15         cin >> x[i][j][k];
    16         sum[i][j][k] = sum[i][j - 1][k] + sum[i][j][k - 1] - sum[i][j - 1][k - 1] + x[i][j][k];
    17     }
    18     for (int sx = 1; sx <= m; sx++)
    19     for (int sy = 1; sy <= n; sy++)
    20     for (int ex = sx; ex <= m; ex++)
    21     for (int ey = sy; ey <= n; ey++){
    22         dp[sx][sy][ex][ey] = -inf;
    23         for (int i = 1; i <= h; i++){
    24             //ptr压缩出来的矩阵块权值和
    25             int ptr = sum[i][ex][ey] - sum[i][sx - 1][ey] - sum[i][ex][sy - 1] + sum[i][sx - 1][sy - 1];
    26             dp[sx][sy][ex][ey] = max(dp[sx][sy][ex][ey] + ptr, ptr);
    27             ans = max(dp[sx][sy][ex][ey], ans);
    28         }
    29     }
    30     cout << ans << endl;
    31     return 0;
    32 }
    View Code
  • 相关阅读:
    TCP的三次握手与四次挥手
    关系型数据库和非关系型数据库的区别
    wedpack打包的基本使用
    express的中间件与next()
    react-redux (react)
    判断数据类型的几种方式
    关于NODE__APP在windows系统解决适配问题
    中间件,前后端分离思想
    移动端
    EasyUI combobox 动态下拉列表
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4605744.html
Copyright © 2011-2022 走看看