玉蟾宮

w1210發表於2024-03-13


求最大子矩陣一般用採用懸線法 (包好用的牢底)
懸線法:

  • [ 以這道題為例,我們將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;
}

相關文章