现在的位置: 首页 > 综合 > 正文

hdu 2870 Largest Submatrix (dp)

2017年10月18日 ⁄ 综合 ⁄ 共 2212字 ⁄ 字号 评论关闭

小记:这个算是1506,1505的再次升级版吧,1506是一维版本,1505是二维版本,这个2870则是可以变动两三次的二维版本。 1A!

思路:如1505一样,我们一行一行的处理, 因为w,x,y,z都可以变,但是a,b,c不能变,那么我们以a,b,c为基础,每个w,x,y,z都变a,或b或c。

即,我们对每一个点计算出它是a或者b或者c时所能得到的最大子矩

h[i][j] 表示当前行第i个字符是j 然后往上碰到第一个不同的字符的高度

l[i][j] 表示当前行第i个字符是j的时候,其左边连续到它这个位置高度大于等于它自己的高度的最长长度

r[i][j] 表示当前行第i个字符是j的时候,其右边连续到它这个位置高度大于等于它自己的高度的最长长度

因为a,b,c不变,所以j 的值只有3个,我们对每个点处理下三个值所能得到的最大值,保存最大的那个就是结果了

if( 当前字符== j ) h[i][j] ++, 其它字符都归0

l[i][j] = l[l[i][j] - 1][j]   (l[i][j] > 0 && h[l[i][j] - 1] >= h[i][j]) (j = 1(a),2( b),3 (c))
r[i][j] = r[l[i][j] - 1][j]   (r[i][j] +1 > m && h[r[i][j] - 1] >= h[i][j])  (j = 1(a), 2(b), 3(c))

初始化 记得 l[i][j] = -1, r[i][j] = m,然后碰到j的时候 就左右都赋值为 i, 高度初始化都为0

code:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>

using namespace std;

#define mst(a,b) memset(a,b,sizeof(a))
#define REP(a,b,c) for(int a = b; a < c; ++a)
#define eps 10e-8

const int MAX_ = 1010;
const int N = 100010;
const int INF = 0x7fffffff;

int h[MAX_][3];
int l[MAX_][3], r[MAX_][3];
char str[MAX_][MAX_];

int main(){
	int n, m, ans;

	while(~scanf("%d%d", &n, &m)){
	    REP(i, 0, m){
            REP(ii, 0, 3){
                l[i][ii] = -1;
                r[i][ii] = m;
                h[i][ii] = 0;
            }
        }
	    ans = -1;
	    
        REP(j, 0, n){
            scanf("%s", str[j]);
            REP(i, 0, m){
                switch(str[j][i]){
                    case 'a': l[i][0] = i; r[i][0] = i; h[i][0]++; h[i][1] = 0; h[i][2] = 0;
                    break;
                    case 'b': l[i][1] = i; r[i][1] = i; h[i][0] = 0; h[i][1] ++; h[i][2] = 0;
                    break;
                    case 'c': l[i][2] = i; r[i][2] = i; h[i][0] = 0; h[i][1] = 0; h[i][2] ++;
                    break;
                    case 'w': l[i][0] = i; r[i][0] = i; l[i][1] = i; r[i][1] = i; h[i][0]++; h[i][1] ++; h[i][2] = 0;
                    break;
                    case 'x': l[i][1] = i; r[i][1] = i; l[i][2] = i; r[i][2] = i; h[i][0] = 0; h[i][1] ++; h[i][2] ++;
                    break;
                    case 'y': l[i][2] = i; r[i][2] = i; l[i][0] = i; r[i][0] = i; h[i][0]++; h[i][1] = 0; h[i][2] ++;
                    break;
                    case 'z': l[i][0] = i; r[i][0] = i; l[i][1] = i; r[i][1] = i; l[i][2] = i; r[i][2] = i; h[i][0] ++; h[i][1] ++; h[i][2] ++;
                    break;
                }
            }
            REP(ii, 0, 3){
                REP(k, 0, m){
                    while(l[k][ii] > 0 && h[l[k][ii] - 1][ii] >= h[k][ii]){
                        l[k][ii] = l[l[k][ii] - 1][ii];
                    }
                }
            }

            REP(ii, 0, 3){
                for(int k = m-1; k > -1; --k){
                    while(r[k][ii] + 1 < m && h[r[k][ii] + 1][ii] >= h[k][ii]){
                        r[k][ii] = r[r[k][ii] + 1][ii];
                    }
                }
            }

            REP(ii, 0, 3){
                REP(k, 0, m){
                    if(l[k][ii] < 0 || r[k][ii] > m-1)continue;
                    int tmp = (r[k][ii] - l[k][ii] + 1) * h[k][ii];
                    //printf(" | (%d %d) = %d | ", l[k][ii], r[k][ii], tmp);
                    ans = max(ans, tmp);
                }
            }
            //printf("\n");
        }
        printf("%d\n", ans);
	}
	return 0;
}
l[i][j] = l[l[i][j] - 1][j]   (l[i][j] > 0 && h[l[i][j] - 1] >= h[i][j])

抱歉!评论已关闭.