悬线法(知识点总结)

暑假学的,当时也没总结,今天又看到,怕再忘了吧……

其实就还是dp的思想,搞来搞去这个样子……

思路来源

https://blog.csdn.net/qq_30358129/article/details/88044727

最大01子矩阵

题目可以用来交poj3494

h[i][j]表示以(i,j)为最下位置的悬线的高度,

l[i][j]表示(i,j)能拓到的最左位置,r[i][j]代表(i,j)能拓到的最右位置

枚举每一行,然后如果上一行有值的话就将同行子矩形变窄,否则不变

以上思想即可解决最大01子矩阵问题,然后单调栈也可以解决

#include<iostream>
#include<cstdio>
using namespace std;
const int N=2e3+10;
int m,n,a[N][N],l[N][N],r[N][N],h[N][N];
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=m;++j)
			{
				scanf("%d",&a[i][j]);
			}
		}
		int L=1e9,R=0,ans=0;
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=m;++j)
			{
				if(a[i][j]==1)L=min(L,j);//尺取连续段最左1的位置 
				else L=1e9;
				l[i][j]=L;
			}
			for(int j=m;j>=1;--j)
			{
				if(a[i][j]==1)R=max(R,j);//尺取连续段最右1的位置 
				else R=0;
				r[i][j]=R; 
			}
			for(int j=1;j<=m;++j)
			{
				if(a[i-1][j])
				{
					h[i][j]=h[i-1][j]+1;
					l[i][j]=max(l[i-1][j],l[i][j]);//收左线
					r[i][j]=min(r[i-1][j],r[i][j]);//收右线 
				}
				else h[i][j]=1;
				if(a[i][j])ans=max(ans,(r[i][j]-l[i][j]+1)*h[i][j]);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

最大同色子矩阵

魔改一下悬线法,把相同颜色的抠出来,考虑什么时候修改l[]和r[]的值

代码将h[j]不更新时初始化为极小/极大,从而将取max和取min对l[]和r[]的修改统一

相同的思想在于,如果上面可以继承,就一定会缩左界和右界,代表悬线必取的左右界

如果仍用单调栈的话,需要套一个尺取

#include<iostream>
#include<cstdio>
using namespace std;
const int N=2e3+10;
typedef long long ll;
int m,n,a[N][N];
int l[N],r[N],h[N];
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=m;++j)
			{
				scanf("%d",&a[i][j]);
			}
		}
		for(int j=1;j<=m;j++)
			l[j]=0,r[j]=m+1,h[j]=0;
		ll ans=0;
		int la,ra;
		for(int i=1;i<=n;++i)
		{
			la=0;ra=m+1;
			for(int j=1;j<=m;++j)
			{
				if(a[i][j]==a[i-1][j])
					h[j]++;
				else 
					h[j]=1,l[j]=0,r[j]=m+1;
				if(a[i][j]==a[i][j-1])
					l[j]=max(l[j],la+1);
				else 
					l[j]=j,la=j-1;//考虑到l[j]<=j而此处l[j]只能等于j
			}
			for(int j=m;j>=1;--j)
			{
				if(a[i][j]==a[i][j+1])
					r[j]=min(r[j],ra-1);
				else 
					r[j]=j,ra=j+1;//同理
				ans=max(ans,1ll*h[j]*(r[j]-l[j]+1)*a[i][j]);
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}
发布了467 篇原创文章 · 获赞 53 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/103460133