hdu 2870 Largest Submatrix (dp)
2014-06-04 12:09
399 查看
小记:这个算是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])
思路:如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])
相关文章推荐
- hdu 2870 Largest Submatrix (DP)
- Largest Submatrix - HDU 2870 dp
- hdu 2870 Largest Submatrix dp 动态规划
- HDU 2870 Largest Submatrix DP求最大子矩阵
- hdu 2870 Largest Submatrix(dp)
- HDU 2870 Largest Submatrix(DP)
- HDU-2870 Largest Submatrix (线性dp 最大01矩阵)(2009 Multi-University Training Contest 7 )
- hdu - 2870 - Largest Submatrix(dp / 单调栈)
- HDU-2870-Largest Submatrix(DP)
- HDU 2870 Largest Submatrix(DP)
- HDU 2870 Largest Submatrix(dp最大子矩阵和)
- HDU 2870 Largest Submatrix
- hdu 2870 Largest Submatrix
- hdu 2870 Largest Submatrixhdu
- hdu 2870 Largest Submatrix
- hdu 2870 - Largest Submatrix
- 【DP+预处理|最长连续子序列】HDU-2870 Largest Submatrix
- hdu 2870 Largest Submatrix
- HDU 2870 Largest Submatrix(最大完全子矩阵之不可移动列)
- HDU - 2870 Largest Submatrix