求最大子矩陣


懸線法

介紹

可以用來解決最大子矩陣問題

原理分析

設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
*/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM