题意简述
请你在一个黑白矩阵中选出一个长方形(含正方形)和正方形的子矩阵,使得所有相邻的点颜色不一样。
矩阵大小:两条边都<=2000<=2000<=2000
数据
输入
3 3
1 0 1
0 1 0
1 0 0
输出
4
6
解释
给定矩阵:

正方形:

长方形:

我的控制台是萌萌哒#ffc0cb粉色
一个小技巧:如果您的控制台是像我的这样能选择的,那么只要按着ALT就可以只选出矩形部分了。
效果图:

思路
悬线DP。我们用L[i][j],R[i][j]L[i][j],R[i][j]L[i][j],R[i][j]分别表示向左,右最远珂以延伸(延伸的条件就是黑白相间)到同一行第几个点。U[i][j]U[i][j]U[i][j]表示向上延伸(延伸条件同上)的最大长度。(这是悬线DP的套路)
然后转移方程很好写。用mpmpmp记录矩阵,枚举i,ji,ji,j,L,RL,RL,R的初始值是jjj,UUU的初始值是1.若mp[i][j−1]!=mp[i][j]mp[i][j-1]!=mp[i][j]mp[i][j−1]!=mp[i][j],则L[i][j]=L[i][j−1]L[i][j]=L[i][j-1]L[i][j]=L[i][j−1],RRR的转移类似。UUU到后面一边DPDPDP一边转移。
那现在就开始DPDPDP了。枚举i,ji,ji,j,表示我们现在选的子矩形的左下角。如果mp[i][j]!=mp[i−1][j]mp[i][j]!=mp[i-1][j]mp[i][j]!=mp[i−1][j],说明我们现在枚举的左下角珂以继承上面的结果。显然要先更新UUU,那我们怎么继承其他的部分呢?

绿色表示当前枚举到的点,红色表示珂以延伸的点。
显然,我们现在这一行珂以左到222,右到444,但是上一行到不了这么远。
所以我们得到,在往下继承的时候,左取minminmin,右取maxmaxmax。
然后你会发现,这样考虑每个子矩形的左下角,所有都会被考虑到。正确性。。。感性证明一下,理性证明我也不会证。
代码:
(以下代码中的leftleftleft就是LLL,rightrightright就是RRR,upupup就是UUU)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 2010
using namespace std;
int mp[N][N];
int left[N][N],right[N][N],up[N][N];
int n,m;
void Input()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&mp[i][j]);
left[i][j]=right[i][j]=j;
up[i][j]=1;//初始化
}
}
}
void Build()
{
for(int i=1;i<=n;i++)
{
for(int j=2;j<=m;j++)
{
if (mp[i][j-1]!=mp[i][j])
{
left[i][j]=left[i][j-1];
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=m-1;j>=1;j--)
{
if (mp[i][j+1]!=mp[i][j])
{
right[i][j]=right[i][j+1];
}
}
}
//预处理left和right
}
void Solve()
{
Build();//也珂以写在main里面,这个代码是一个星期前写的,由于心情的问题,会有一点点风格的影响
//写代码也要体现自己的情感,就像写诗一样。做到"诗如代码,代码如诗"
int ans1=0,ans2=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if (i>1 and mp[i][j]!=mp[i-1][j])//继承
{
left[i][j]=max(left[i][j],left[i-1][j]);
right[i][j]=min(right[i][j],right[i-1][j]);
up[i][j]=up[i-1][j]+1;//更新U
}
int a=right[i][j]-left[i][j]+1;
int b=min(a,up[i][j]);
ans1=max(ans1,b*b);
ans2=max(ans2,a*up[i][j]);//更新答案
//注意正方形和长方形的区别
}
}
printf("%d\n%d\n",ans1,ans2);
}
main()
{
Input();
Solve();
return 0;
}
本文详细介绍了如何解决一个关于在黑白矩阵中选取特定形状(正方形或长方形)的子矩阵的问题,使得相邻点颜色不同。作者通过解析题意、提供数据示例,并给出思路,讲解了使用悬线DP的方法来解决此问题,包括状态定义、转移方程以及代码实现。
316

被折叠的 条评论
为什么被折叠?



