Live2D

玉蟾宫(悬线dp)


求最大子矩阵一般用采用悬线法 (包好用的牢底)
悬线法:

  • [ 以这道题为例,我们将R称为障碍格子,将F称为非障碍格子]
  • 我们选择任意一个非障碍格子,引出三条直线:左直 右直 上直

  • 随后从这个点出发,分别向上 左 右延申直到遇到障碍格

我们要求上悬线尽可能高的面积, 但有可能上一层的左直线比这一层短,所以不能直接傻傻地用上*(右-左+1);
所以要让左悬线尽可能大,右悬线尽可能小
最后轮流求每个非障碍点能延伸到的最大面积

公主请欣赏代码
#include<bits/stdc++.h>
using namespace std;

const int N = 1e3+10;
int n, m, ans;
char a[N][N];
int h[N][N], l[N][N], r[N][N];

int main(){
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++){
		for(int j=1; j<=m; j++){
			cin >> a[i][j];
			h[i][j] = 1; l[i][j] = r[i][j] = j;//将悬线都初始化
		}
	}
	for(int i=1; i<=n; i++){
		for(int j=1; j<=m; j++){
			if(a[i][j] == 'F' and a[i][j-1] == 'F') l[i][j] = l[i][j-1];//延伸左悬线
		}
		for(int j=1; j<=m; j++){
			if(a[i][j] == 'F' and a[i-1][j] == 'F') h[i][j] = h[i-1][j] + 1;//延伸上悬线
		}
		for(int j=m; j>=1; j--){
			if(a[i][j] == 'F' and a[i][j+1] == 'F') r[i][j] = r[i][j+1];//延伸右悬线
		}
	}
	for(int i=1; i<=n; i++){
		for(int j=1; j<=m; j++){
			if(a[i][j] == 'F' and a[i-1][j] == 'F'){
				l[i][j] = max(l[i][j], l[i-1][j]);
				r[i][j] = min(r[i][j], r[i-1][j]);
			}
			if(a[i][j] == 'F'){
				ans = max(ans, h[i][j] * (r[i][j] - l[i][j] + 1));
			}
		}
	}
	printf("%d", ans*3);
	return 0;
}
posted @ 2024-02-22 16:50  w1210  阅读(13)  评论(0编辑  收藏  举报