BZOJ 1057 ZJOI 2007 棋盘制作 DP+悬线法

题目大意:给出一个由01形成的矩阵,问这个矩阵中最大面积的正方形和矩形,其中任意一个方块相邻的都是不同的格子。

思路:其实吧所有(i + j)&1的位置上的数字异或一下,就变成都是0或者都是1的最大正方形和矩形了。第一问就是水DP,第二问可以单调栈或者悬线。都很好写。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 2010
using namespace std;

int m,n;
int src[MAX][MAX];
int f[MAX][MAX];

int up[MAX][MAX],_left[MAX][MAX],_right[MAX][MAX];

int main()
{
	cin >> m >> n;
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= n; ++j) {
			scanf("%d",&src[i][j]);
			if((i + j)&1)
				src[i][j] ^= 1;
		}
	int ans = 0;
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= n; ++j)
			if(src[i][j]) {
				f[i][j] = min(f[i - 1][j - 1],min(f[i - 1][j],f[i][j - 1])) + 1;
				ans = max(ans,f[i][j]);
			}
	memset(f,0,sizeof(f));
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= n; ++j)
			if(!src[i][j]) {
				f[i][j] = min(f[i - 1][j - 1],min(f[i - 1][j],f[i][j - 1])) + 1;
				ans = max(ans,f[i][j]);
			}
	cout << ans * ans << endl;
	ans = 0;
	for(int i = 1; i <= m; ++i) {
		for(int j = 1; j <= n; ++j)
			_left[i][j] = src[i][j] ? _left[i][j - 1] + 1:0;
		for(int j = n; j; --j)
			_right[i][j] = src[i][j] ? _right[i][j + 1] + 1:0;
	}
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= n; ++j)
			if(src[i][j] && src[i - 1][j]) {
				up[i][j] = up[i - 1][j] + 1;
				_left[i][j] = min(_left[i][j],_left[i - 1][j]);
				_right[i][j] = min(_right[i][j],_right[i - 1][j]);
				ans = max(ans,(_left[i][j] + _right[i][j] - 1) * (up[i][j] + 1));
			}
	memset(_left,0,sizeof(_left));
	memset(_right,0,sizeof(_right));
	memset(up,0,sizeof(up));
	for(int i = 1; i <= m; ++i) {
		for(int j = 1; j <= n; ++j)
			_left[i][j] = src[i][j] ? 0:_left[i][j - 1] + 1;
		for(int j = n; j; --j)
			_right[i][j] = src[i][j] ? 0:_right[i][j + 1] + 1;
	}
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= n; ++j)
			if(!src[i][j] && !src[i - 1][j]) {
				up[i][j] = up[i - 1][j] + 1;
				_left[i][j] = min(_left[i][j],_left[i - 1][j]);
				_right[i][j] = min(_right[i][j],_right[i - 1][j]);
				ans = max(ans,(_left[i][j] + _right[i][j] - 1) * (up[i][j] + 1));
			}
	cout << ans << endl;
	return 0;
}

时间: 2024-11-07 09:54:39

BZOJ 1057 ZJOI 2007 棋盘制作 DP+悬线法的相关文章

BZOJ 1057: [ZJOI2007]棋盘制作( dp + 悬线法 )

对于第一问, 简单的dp. f(i, j)表示以(i, j)为左上角的最大正方形, f(i, j) = min( f(i + 1, j), f(i, j + 1), f(i + 1, j + 1)) + 1 (假如(i, j)和右边和下边不冲突) 第二问就是经典的悬线法解决最大子矩阵了, 维护悬线H[i][j], 左边右边延伸的最长距离.先一行一行求出这一行的L, R, 然后再从上往下扫, 维护H, L, R 写完我才发现我脑残了...最大的正方形一定是在最大子矩阵里面啊...所以其实不用dp.

[BZOJ 1057][ZJOI 2007]棋盘制作(最大全0/1子矩阵)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1057 这题好像很早之前就看到过...那时候我还只会玩脚丫子,做这题完全像SB一样,记得那时我做了一会就放弃了. 如今看到这题感觉好做多了,此题预处理很巧妙,我们看一个棋盘,它的所有黑点的行标奇偶性都相同,列标的奇偶性也都相同.白点一样. 于是我们就可以预处理下,对于所有行标和列标奇偶性相同的点,保持它们的颜色不变,奇偶性不相同的点,反转它们的颜色,于是预处理后,我们要找的矩形在整

bzoj1057: [ZJOI2007]棋盘制作(悬线法)

题目要求纵横坐标和奇偶性不同的点取值不同,于是我们把纵横坐标和奇偶性为1的点和0的点分别取反,就变成经典的最大全1子矩阵问题了,用悬线法解决. #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; const int maxn=2010,inf=1e9; int n,m,ans1,ans2; int h[maxn],mp[max

[ZJOI2007]棋盘制作(悬线法)

题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则. 小Q找到了一张由N \times MN×M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减一部分作为新

【BZOJ 1057】 [ZJOI2007]棋盘制作

1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 1496  Solved: 753 [Submit][Status] Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘

bzoj 3039: 玉蟾宫 单调栈或者悬线法求最大子矩阵和

3039: 玉蟾宫 Time Limit: 2 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地.这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda.现在freda要在这里卖萌...它要找一块矩形土地,要求这片土地都标着'

最大子矩阵问题&amp;悬线法小结

\(\large{例题1.}\) \(\large{\text{ZJOI}2007棋盘制作}\) \(\\\) \(\large{证明一下做法的正确性,首先如果一个矩形面积最大,那么它一定顶着边界.\\然后更新up.l.r当且仅当a[i][j] 与 a[i-1][j]满足一定的关系,对其余的up.l与r无影响,也就对最大矩阵无影响.}\) \(\\\) \(\Large\textbf{Code: }\) #include <bits/stdc++.h> #define gc() getchar

BZOJ 1057: [ZJOI2007]棋盘制作 悬线法求最大子矩阵+dp

1057: [ZJOI2007]棋盘制作 Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则.小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减

【BZOJ-3039&amp;1057】玉蟾宫&amp;棋盘制作 悬线法

3039: 玉蟾宫 Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 753  Solved: 444[Submit][Status][Discuss] Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地.这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda.现在freda要在这里卖