暑期dp46道(39)--HDOJ 2870 最大子矩阵面积...

题目链接:HDOJ 2870



题意:给定一个仅由'a','b','c','w','x','y','z'组成的字符矩阵,且你可以把'w' 转成 (to)'a' 或 'b', 'x' to 'b' or 'c', 'y' to 'a' or 'c',  'z' to 'a', 'b' or 'c',求能转成的最大子矩阵面积;




题解:毫无疑问,对于'a','b','c'三种子矩阵,最大的时候一定是能转则转,总不能已经打算,所以分开考虑,每次转一种字符,求最大,然后求三个最大值的max,结束,这个矩阵求法,以前的博文里也有,那段时间 博客更新没有接上,直接补上 前面的链接:HDU 1505 题解  HDU 1506题解


此题代码:

#include<cstdio>
#include<cstring>
#include<string>

#define debug 0
#define M(a) memset(a,0,sizeof(a))
#define Max(a,b) ((a>b)?a:b)

const int maxn = 1000 + 5;
int l[maxn][maxn], r[maxn][maxn], h[maxn][maxn], data[maxn][maxn], ans;
int n, m;
int dir[][4] = { { 1,4,6,7 },{ 2,4,5,7 },{ 3,5,6,7 } };//用数组记录可转的字符情况

bool is(int a, int b)
{
	for (int i = 0; i<4; i++)
	{
		if (dir[b - 1][i] == a)
			return true;
	}
	return false;
}
void Do()
{
	int temp, maxn;
	for (int i = 1; i<4; i++)
	{
		maxn = 0;
		M(l);
		M(r);
		M(h);
		for (int j = 1; j <= n; j++)
		{
			for (int k = 1; k <= m; k++)
			{
				if (is(data[j][k], i))//判断当前的是否可转,和以前的矩阵是否为0是一样的
					h[j][k] = h[j - 1][k] + 1;
				else
					h[j][k] = 0;
			}
		}
		for (int j = 1; j <= n; j++)//求最大子矩阵面积
		{
			h[j][0] = h[j][m + 1] = -1;
			for (int k = 1; k <= m; k++)
			{
				temp = k - 1;
				while (h[j][temp] >= h[j][k])
				{
					temp = l[j][temp];
				}
				l[j][k] = temp;
			}
			for (int k = m; k >= 1; k--)
			{
				temp = k + 1;
				while (h[j][temp] >= h[j][k])
				{
					temp = r[j][temp];
				}
				r[j][k] = temp;
			}
			for (int k = 1; k <= m; k++)
			{
				//printf("%d%d\n",r[j][k],l[j][k]);
				maxn = Max(maxn, (r[j][k] - l[j][k] - 1)*h[j][k]);
			}
		}
		ans = Max(ans, maxn);
	}
	printf("%d\n", ans);
}
int main()
{
#if debug
	freopen("in.txt", "r", stdin);
#endif//debug
	char a;
	int temp;
	while (~scanf("%d%d", &n, &m))
	{
		ans = 0;
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= m; j++)
			{
				while ((a = getchar()) == '\n' || a == ' ');
				switch (a)//字符转为整数,用于数组记录
				{
					case 'a':temp = 1; 
						break;
					case 'b':temp = 2;
						break;
					case 'c':temp = 3; 
						break;
					case 'w':temp = 4; 
						break;
					case 'x':temp = 5; 
						break;
					case 'y':temp = 6; 
						break;
					case 'z':temp = 7; 
						break;
					default:break;
				}
				//putchar(a);
				data[i][j] = temp;
			}
		}
		Do();
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值