zoukankan      html  css  js  c++  java
  • 求最大子矩阵

    悬线法

    介绍

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

    原理分析

    设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
    */
    
  • 相关阅读:
    产品经理做产品设计的九步法
    产品经理要懂多少技术?
    产品经理如何注重细节意识的培养
    产品经理如何在技术人员面前更有说服力?
    从程序员到项目经理:每个人都是管理者
    我的人才管理方式
    一个关于内部类的小例子
    java中的全局变量与静态变量的区别与联系?有时候为什么专门定义静态变量。(标题党~~)
    举一反三,一小步。
    中国移动的企业文化 ,以及中国移动都有那些业务?
  • 原文地址:https://www.cnblogs.com/Thomastine/p/11827955.html
Copyright © 2011-2022 走看看