求最大子矩阵

悬线法

介绍

可以用来解决最大子矩阵问题

原理分析

设L/R[i][j]表示自点(i,j)向左/右在不经过障碍点情况下能达到的最远点横坐标(图是数组画法时的横坐标),up[i][j]表示(i,j)向上能达到的最远点,初始化为up[i][j] = 1;R[i][j] = L[i][j] = j;得到的是(R-L+1) * up的一个矩阵,如果上面也是合法矩形,那么就合并两个矩形更新答案。但是是否不合并更好呢?当然可能,不过这种情况下上下两矩形的(R - L + 1)不同,在不接合的点会考虑此情况。

例题

Luogu-P4147

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid  ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
	char c = getchar(),f = 1;x = 0;
	for(;c ^ '-' && !isdigit(c);c = getchar());
	if(c == '-') c = getchar(),f = -1;
	for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
	x *= f;
}
template<typename xxx>void print(xxx x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
const int maxn = 2010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
char s[maxn];
int a[maxn][maxn];
int R[maxn][maxn];//表示从(i,j)这个点出发向右能到达最远的点横坐标 
int	L[maxn][maxn];//表示从(i,j)这个点出发向左能到达最远的点横坐标 
int	up[maxn][maxn];//向上到达最远点的距离 
int n,m;
int main() {
	int ans = 0;
	read(n);read(m);
	for(rint i = 1;i <= n; ++i) {
		for(rint j = 1;j <= m; ++j) {
			scanf("%s",s);
			if(s[0] == 'F') a[i][j] = 1;
			up[i][j] = 1;
			R[i][j] = L[i][j] = j;
		}
	}
	for(rint i = 1;i <= n; ++i) {
		for(rint j = 2;j <= m; ++j) {
			if(a[i][j] && a[i][j - 1]) {
				L[i][j] = L[i][j - 1];
			}
		} 
	} 
	for(rint i = 1;i <= n; ++i) {
		for(rint j = m - 1; j; --j) {
			if(a[i][j] && a[i][j + 1]) {
				R[i][j] = R[i][j + 1];
			}
		} 
	} 
	for(rint i = 1;i <= n; ++i) {
		for(rint j = 1;j <= m; ++j) {
			if(i > 1) {
				if(a[i][j] && a[i - 1][j]) {
					L[i][j] = max(L[i][j],L[i - 1][j]);
					R[i][j] = min(R[i][j],R[i - 1][j]);
					up[i][j] = up[i - 1][j] + 1;
				}
			}
			ans = max(ans,(R[i][j] - L[i][j] + 1) * up[i][j]);
		}
	}
	print(ans * 3);
	return 0;
}
/*

*/

枚举障碍点法???

简介

如果方格图过大又不便离散化,且障碍点很少,那么此法更优。

原理分析

参见浅谈用极大化思想解决最大子矩形问题--王知昆,注意,部分有误。

例题

Luogu-P1578

#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include <queue> 
#include <map> 
#include <set> 
#include <bitset>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
template<typename xxx>inline void read(xxx &x) {
	x = 0;int f = 1;char c = getchar();
	for(;c ^ '-' && !isdigit(c);c = getchar());
	if(c == '-') f = -1,c = getchar();
	for(;isdigit(c);c = getchar()) x = (x << 3) + (x << 1) + (c ^ '0');
	x *= f;  
}
template<typename xxx>inline void print(xxx x) {
	if(x < 0) {
		putchar('-');
		x = -x;
	}
	if(x > 9) print(x / 10);
	putchar(x % 10 + '0');
}
const int maxn = 100010;
const int mod = 1e9 + 7;
const int inf = 0x7f7f7f7f;
struct node{
	int xi,yi;
}g[maxn];
inline bool gmp1(node a,node b) {
	if(a.xi == b.xi) return a.yi < b.yi;
	return a.xi < b.xi;
}
inline bool gmp2(node a,node b) {
	if(a.yi == b.yi) return a.xi < b.xi;
	else return a.yi < b.yi;
}
int n,L,W,ans;
int main() {
	read(L);read(W);read(n);
	for(rint i = 1;i <= n; ++i) {
		read(g[i].xi);
		read(g[i].yi);
	}
	++n;g[n] = (node){0,0};
	++n;g[n] = (node){L,W};
	++n;g[n] = (node){0,W};
	++n;g[n] = (node){L,0};
	stable_sort(g + 1,g + n + 1,gmp1);
	for(rint i = 1;i <= n; ++i) {
		int up = W,d = 0;
		for(rint j = i + 1;j <= n; ++j) {
			ans = Max(ans,(g[j].xi - g[i].xi) * (up - d));
			if(g[j].yi < g[i].yi) d = Max(d,g[j].yi);
			else up = Min(g[j].yi,up);
		}
	}
	for(rint i = n; i; --i) {
		int up = W,d = 0;
		for(rint j = i - 1; j; --j) {
			ans = Max(ans,(g[i].xi - g[j].xi) * (up - d));
			if(g[j].yi < g[i].yi) d = Max(d,g[j].yi);
			else up = Min(g[j].yi,up);
		}
	}
	stable_sort(g + 1,g + n + 1,gmp2);
	for(rint i = 2;i <= n; ++i) {
		ans = Max(ans,(g[i].yi - g[i - 1].yi) * L);
	}
	print(ans);
}
/*
4 7
5
0 6
0 0
3 2
1 0
0 3
21

10 10
2 
8 1 
3 9 
80

10 10
3 
3 0 
8 2 
3 9
72

5 5 
3 
1 3 
3 1 
3 4
12

10 10
6
1 2
3 2
6 2
2 1
2 3
2 5
64
*/
原文地址:https://www.cnblogs.com/Thomastine/p/11827955.html