[BZOJ1057][ZJOI2007]棋盘制作(极大子矩形)
2016-11-07 20:41
253 查看
=== ===
这里放传送门=== ===
题解
求解极大子矩形的常用方法之一——悬线法。实质上是一种DP,时间复杂度O(nm)。所谓悬线,就是一条以某个点(i,j)为下端点,上端点尽量往上延伸的一条线段。对于一条悬线我们通常存储三个信息:它的长度,它向左最多能平移的位置,它向右最多能平移的位置。这样的话每条悬线左右平移构造出的子矩形就能保证在上边界和左右边界都是极大的,那么作为答案的极大子矩形必然就是悬线子矩形的一个子集。处理悬线的时候考虑点(i,j)对应的悬线和点(i-1,j)对应的悬线的关系,这道题要求相邻的两个不能同色,那么如果(i-1,j)这个点和(i,j)这个点不同色,那么(i,j)就可以接在(i-1,j)对应的那条悬线的下面。但如果这两个点同色,那么(i,j)这个点对应的悬线长度就会被初始化为1。这样就得到了悬线长度的递推关系;对于左右边界的递推,我们对每个点预处理一下这个点如果保证颜色交替的那个限制最多往左右两边能扩展多大距离。当(i,j)这个悬线只有它一个点的时候这条悬线能左右平移的距离就是这个点能左右平移的距离,否则就要进行一个递推,即把当前悬线分为两部分,就是新增加的这个点(i,j)和原来处理好的悬线(i-1,j),从这两个东西的左右边界里面取个交集就可以了。
最后就是计算结果了,对于这道题要求的最大矩形,直接枚举每一条悬线,它贡献的答案就是长度*左右边界的长度,而对于最大的正方形,(如果经常折纸就会发现)最大的正方形一定是由最大的矩形变过来的,所以就找那个矩形较小的那一条边构造正方形就可以了。
代码
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,ans1,ans2; struct point{ int v,pre,nxt; }a[2010][2010]; struct line{ int h,l,r; }p[2010][2010]; int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ scanf("%d",&a[i][j].v); a[i][j].pre=a[i][j].nxt=j; } for (int i=1;i<=n;i++){ for (int j=2;j<=m;j++) if (a[i][j].v==a[i][j-1].v^1) a[i][j].pre=a[i][j-1].pre; for (int j=m-1;j>=1;j--) if (a[i][j].v==a[i][j+1].v^1) a[i][j].nxt=a[i][j+1].nxt; } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ p[i][j].h=1; p[i][j].l=a[i][j].pre; p[i][j].r=a[i][j].nxt; } for (int i=2;i<=n;i++) for (int j=1;j<=m;j++) if (a[i][j].v==a[i-1][j].v^1){ p[i][j].h+=p[i-1][j].h; p[i][j].l=max(p[i][j].l,p[i-1][j].l); p[i][j].r=min(p[i][j].r,p[i-1][j].r); } ans1=ans2=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ int A,B; A=p[i][j].h; B=p[i][j].r-p[i][j].l+1; if (A>B) swap(A,B); ans1=max(ans1,A*A);//处理正方形的情况 ans2=max(ans2,A*B); } printf("%d\n%d\n",ans1,ans2); return 0; }
相关文章推荐
- bzoj 1057: [ZJOI2007]棋盘制作 求最大全0/1矩阵(极大扩展矩阵)动态规划
- BZOJ1057 [ZJOI2007]棋盘制作 【最大同色矩形】
- BZOJ1057 [ZJOI2007]棋盘制作 【最大同色矩形】
- [BZOJ1057][ZJOI2007]棋盘制作(悬线法)
- BZOJ 1057 ZJOI2007 棋盘制作 单调栈
- [BZOJ1057][ZJOI2007]棋盘制作 单调栈
- bzoj 1057: [ZJOI2007]棋盘制作
- 【BZOJ】1057: [ZJOI2007]棋盘制作(单调栈)
- bzoj1057 [ZJOI2007]棋盘制作
- [BZOJ 1057][ZJOI 2007]棋盘制作(最大全0/1子矩阵)
- [BZOJ1057][ZJOI2007]棋盘制作 (单调栈/悬线法)
- 【LuoguP1169 bzoj1057】[ZJOI2007]棋盘制作
- BZOJ 1057 [ZJOI2007]棋盘制作
- [bzoj1057][ZJOI2007]棋盘制作
- 【BZOJ 1057】 1057: [ZJOI2007]棋盘制作
- [悬线法] BZOJ1057 [ZJOI2007]棋盘制作
- BZOJ 1057: [ZJOI2007]棋盘制作
- Bzoj1057 [ZJOI2007]棋盘制作
- [BZOJ1057]ZJOI2007棋盘制作|DP|单调栈
- 【bzoj 1057】[ZJOI2007] 棋盘制作