zoukankan      html  css  js  c++  java
  • DP小技巧——悬线法

    本来以为之前写过这个方法,今天又考了一道模板题,于是就记录一下

    悬线法是求解一类极大子矩阵问题的DP解法(maybe

    例题:给一个01矩阵,求最大的一个子矩阵,使得该子矩阵全为1

    考试有人想出了(O(n^2log^2n))的二分套二分做法,在此表示膜拜(即二分面积,枚举面积的约数)

    从暴力方面想,对于一个点,直接求出它向左右上的最远距离再乘起来可能不对,所以只能求其中一个的最远距离

    具体来说,定义(u_{i,j})表示从((i,j))向上走能走出的最远距离,(l,r)必须受到(u)的约束,所以定义为满足(u)最大,矩阵合法的条件下可以向左/右走到的最远点,那么(ans=max(u_{i,j}*(r_{i,j}-l_{i,j}+1)))

    形象来看,可以理解为以((i,j))这个点为下端的连续的1组成的一根竖线,这根线左右移动所形成的矩形区域即这个点对应的矩形,这些矩形面积的最大值即为答案

    显然(u,l,r)三个数组可以(O(n^2))递推(见代码),正确性:1.由上面的定义可知,所有的矩阵合法(是子矩阵) 2.最大的矩阵中一定存在一根等于矩形高度的悬线(该线可以左右移动形成该矩阵),如果不存在,即所有的悬线都比该矩阵高,那显然它不是最大矩阵

    Code

    #include<bits/stdc++.h>
    #define N 1005
    #define Min(x,y) ((x)<(y)?(x):(y))
    #define Max(x,y) ((x)>(y)?(x):(y))
    using namespace std;
    int n,m,a[N][N],ans;
    int up[N][N],l[N][N],r[N][N];
    
    template <class T>
    void read(T &x)
    {
    	char c;int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
    }
    
    int main()
    {
    	read(n);read(m);
    	for(int i=1;i<=n;++i)
    	  for(int j=1;j<=m;++j) 
    	    read(a[i][j]);
    	for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j)
    	{
    		if(a[i][j])
    		{
    			l[i][j]=r[i][j]=j;
    			up[i][j]=1;
    		}
    	}
    	for(int i=1;i<=n;++i)
    	  for(int j=2;j<=m;++j)
    		if(a[i][j]&&a[i][j-1]) 
    		  l[i][j]=l[i][j-1];
    	for(int i=1;i<=n;++i)
    	  for(int j=m-1;j>=1;--j)
    		if(a[i][j]&&a[i][j+1]) 
    		  r[i][j]=r[i][j+1];
    	for(int i=1;i<=n;++i)
    	{
    		for(int j=1;j<=m;++j)
    		{
    			if(i-1&&a[i-1][j]&&a[i][j])
    			{
    				up[i][j]=up[i-1][j]+1;
    				l[i][j]=Max(l[i][j],l[i-1][j]);
    				r[i][j]=Min(r[i][j],r[i-1][j]);
    			}
    			ans=Max(ans,(r[i][j]-l[i][j]+1)*up[i][j]);
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

    习题:玉蟾宫其实就是例题),棋盘制作(强行将高和宽取(min)即可保证为正方形)

  • 相关阅读:
    leetcode 5286 网格中的最短路径
    C++ STL
    Transformer解读
    global_steps
    tensorflow中的一些语法问题
    生成器与yield关键字
    CNN神经网络一维卷积和二维卷积
    electron-builder打包后,运行的程序左上角图标不显示,桌面和状态栏的显示正常,是什么情况。
    git慢设置代理
    js使用正则表达式获取字符串中特定的字符
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11635611.html
Copyright © 2011-2022 走看看