和最大子矩阵 ZUFEOJ

问题 H: 吃西瓜

时间限制: 1 Sec  内存限制: 256 MB
提交: 8  解决: 6
[提交][状态][讨论版][命题人:外部导入]

题目描述

 

【问题描述】

老胡买了是长方体形的西瓜来犒劳大家....

这块西瓜长m厘米,宽n厘米,高h厘米.他发现如果把这块西瓜平均地分成m*n*h块1立方厘米的小正方体,那么每一小块都会有一个营养值(可能为负,因为西瓜是有可能坏掉的,但是绝对值不超过200)。

现在老胡决定从这m*n*h立方厘米的西瓜中切出mm*nn*hh(0<=mm<=m,0<=nn<=n,0<=hh<=h)立方厘米的一块小西瓜(一定是立方体形,长宽高均为整数),送给该场比赛最高分获得者补充营养。他想知道他最多能获得多少营养值。

换句话说,我们希望从一个m*n*h的三维矩阵中,找出一个三维子矩阵,这个子矩阵的权和最大.

 

一个2*3*4的例子,最优方案为切红色2*3*1部分。

【文件输入】matrix.in

首行三个正整数h,m,n(注意顺序),分别表示西瓜的高,长,宽.

以下h部分,每部分是一个m*n的矩阵,第i部分第j行的第k个数表示西瓜第i层,第j行第k列的那块1立方厘米的小正方体的营养值.

【文件输出】matrix.out

老胡所能得到的最大营养值

【输入输出样例】

matrix.in

matrix.out

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

45

【数据规模】

对于30%的数据,h=1,1<=m,n<=10

对于全部的数据,1<=h<=32,1<=m,n<=50,保证h<=m,n

[说明]此题中出现的所有数全为整数。

 

 

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int inf = 2e9;

int h, m, n;
int a[55][55][55];

int qian[55], mi[55];
int cal(int t[])
{
	int ans = -inf;
	qian[0] = 0;
	for (int i = 1; i <= h; i++)
	{
		qian[i] = qian[i - 1] + t[i];
		mi[i] = min(mi[i - 1], qian[i]);
		ans = max(ans, qian[i] - mi[i - 1]);
	}
	return ans;
}

int t[55];
int sum[55][55][55];
int main()
{
	cin >> h >> m >> n;
	for (int i = 1; i <= h; i++)
		for (int j = 1; j <= m; j++)
		for (int k = 1; k <= n; k++)
		cin >> a[i][j][k];
	
	for (int i = 1; i <= h; i++)
	{
		for (int j = 1; j <= m; j++)
		for (int k = 1; k <= n; k++)
		sum[i][j][k] = sum[i][j - 1][k] + sum[i][j][k - 1] - sum[i][j - 1][k - 1] + a[i][j][k];
	}
	
	int ans = 0;
	for (int i = 1; i <= m; i++)		// 枚举四边界
		for (int j = i; j <= m; j++)
			for (int p = 1; p <= n; p++)
				for (int q = p; q <= n; q++)
	{
		for (int hh = 1; hh <= h; hh++)		// 将取出的方块每一层加成一个数
			t[hh] = sum[hh][j][q] - sum[hh][j][p - 1] - sum[hh][i - 1][q] + sum[hh][i - 1][p - 1];
		ans = max(ans, cal(t));		// 在新得到的串中 O(n) 取和最大的一段
	}
	cout << ans << endl;
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值