BZOJ 1057 悬线法求最大01矩阵
1057: [ZJOI2007]棋盘制作
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3917 Solved: 2046
[Submit][Status][Discuss]
Description
国际象棋是世界上最古老的博弈游戏之一,和中国的围棋、象棋以及日本的将棋同享盛名。据说国际象棋起源
于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳。而我们的主人公小Q,
正是国际象棋的狂热爱好者。作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定
将棋盘扩大以适应他们的新规则。小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种
颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。不过小Q还没有决定是找
一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他
希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。于是小Q找到了即将参加全
国信息学竞赛的你,你能帮助他么?
Input
第一行包含两个整数N和M,分别表示矩形纸片的长和宽。接下来的N行包含一个N * M的01矩阵,表示这张矩形
纸片的颜色(0表示白色,1表示黑色)。
Output
包含两行,每行包含一个整数。第一行为可以找到的最大正方形棋盘的面积,第二行为可以找到的最大矩形棋
盘的面积(注意正方形和矩形是可以相交或者包含的)。
Sample Input
3 3
1 0 1
0 1 0
1 0 0
1 0 1
0 1 0
1 0 0
Sample Output
4
6
6
HINT
N, M ≤ 2000
Source
复杂度:O(n * m)
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define pli pair<ll, int> 29 #define pil pair<int, ll> 30 #define clr(a, x) memset(a, x, sizeof(a)) 31 32 const double pi = acos(-1.0); 33 const int INF = 0x3f3f3f3f; 34 const int MOD = 1e9 + 7; 35 const double EPS = 1e-9; 36 37 /* 38 #include <ext/pb_ds/assoc_container.hpp> 39 #include <ext/pb_ds/tree_policy.hpp> 40 using namespace __gnu_pbds; 41 #define TREE tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> 42 TREE T; 43 */ 44 45 46 int n, m, mmp[2015][2015], ans1, ans2; 47 int h[2015][2015], l[2015][2015], r[2015][2015]; 48 int main() { 49 scanf("%d%d", &n, &m); 50 for (int i = 1; i <= n; ++i) { 51 for (int j = 1; j <= m; ++j) { 52 scanf("%d", &mmp[i][j]); 53 } 54 } 55 for (int i = 1; i <= n; ++i) { 56 for (int j = 1; j <= m; ++j) { 57 if (j > 1 && mmp[i][j - 1] != mmp[i][j]) { 58 l[i][j] = l[i][j - 1]; 59 r[i][j] = r[i][j - 1]; 60 } else { 61 l[i][j] = j; 62 int k; 63 for (k = j + 1; k <= m; ++k) { 64 if (mmp[i][k] == mmp[i][k - 1]) break; 65 } 66 r[i][j] = k - 1; 67 } 68 } 69 for (int j = 1; j <= m; ++j) { 70 if (i > 1 && mmp[i - 1][j] != mmp[i][j]) { 71 h[i][j] = h[i - 1][j] + 1; 72 l[i][j] = max(l[i][j], l[i - 1][j]); 73 r[i][j] = min(r[i][j], r[i - 1][j]); 74 } else { 75 h[i][j] = 1; 76 } 77 ans2 = max(ans2, h[i][j] * (r[i][j] - l[i][j] + 1)); 78 int d = min(h[i][j], r[i][j] - l[i][j] + 1); 79 ans1 = max(ans1, d * d); 80 } 81 } 82 printf("%d\n%d\n", ans1, ans2); 83 return 0; 84 }