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

来源:互联网 发布:java网盘系统源码 编辑:程序博客网 时间:2024/05/16 18:34

题目链接: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;elseh[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 debugfreopen("in.txt", "r", stdin);#endif//debugchar 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
原创粉丝点击