1057: [ZJOI2007]棋盘制作

Time Limit: 20 Sec  Memory Limit: 162 MB

Submit: 3248  Solved: 1636

[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

Sample Output

4

6

HINT

N, M ≤ 2000

好像以前写过?

再写一遍加深印象

开一个sum[i][j]表示位置(i,j)能向右同色延伸的最大长度

我们先定下矩形的左边所在列,对该列中的点按向右延伸长度降序排序,然后枚举每个点

这样子每次枚举出的点对应的宽一定是当前最小的【宽】,再用并查集维护其向上向下最长延伸距离【长】,

我们就可以得出以该点为向右为宽的最大矩形面积

而我们最后求出的矩形的宽一定会受其中至少一个点向右延伸长度的束缚

当我们枚举到答案中影响宽的那一个点的时候就一定能更新出最优答案

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define LL long long int
  6. #define REP(i,n) for (int i = 1; i <= (n); i++)
  7. #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
  8. using namespace std;
  9. const int maxn = 2005,maxm = 100005,INF = 1000000000;
  10. inline int RD(){
  11. int out = 0,flag = 1; char c = getchar();
  12. while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
  13. while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
  14. return out * flag;
  15. }
  16. int A[maxn][maxn],sum[maxn][maxn],N,M,up[maxn],down[maxn],ans1 = 0,ans2 = 0;
  17. bool vis[maxn];
  18. struct node{int i,len;}e[maxn];
  19. inline bool operator < (const node& a,const node& b){return a.len > b.len;}
  20. inline int findu(int u){return u == up[u] ? u : up[u] = findu(up[u]);}
  21. inline int findd(int u){return u == down[u] ? u : down[u] = findd(down[u]);}
  22. void solve(){
  23. for (int i = 1; i <= N; i++){
  24. sum[i][M] = 1;
  25. for (int j = M - 1; j > 0; j--)
  26. sum[i][j] = A[i][j] == A[i][j + 1] ? sum[i][j + 1] + 1 : 1;
  27. }
  28. for (int j = 1; j <= M; j++){
  29. for (int i = 1; i <= N; i++){
  30. e[i].i = i; e[i].len = sum[i][j]; down[i] = up[i] = i; vis[i] = false;
  31. }
  32. sort(e + 1,e + 1 + N);
  33. for (int i = 1; i <= N; i++){
  34. int k = e[i].i; vis[k] = true;
  35. //printf("(%d,%d) len = %d %d\n",k,j,e[i].len,ans1);
  36. if (k > 1 && vis[k - 1] && A[k - 1][j] == A[k][j]){
  37. up[k] = findu(k - 1);
  38. down[k - 1] = k;
  39. }
  40. if (k < N && vis[k + 1] && A[k + 1][j] == A[k][j]){
  41. down[k] = findd(k + 1);
  42. up[k + 1] = k;
  43. }
  44. int u = findu(k),d = findd(k),ed = min(e[i].len,d - u + 1);
  45. //printf("%d %d\n",u,d);
  46. ans1 = max(ans1,ed * ed);
  47. ans2 = max(ans2,e[i].len * (d - u + 1));
  48. }
  49. }
  50. }
  51. int main(){
  52. N = RD(); M = RD();
  53. REP(i,N) REP(j,M) A[i][j] = RD() ^ ((i & 1) ^ (j & 1));
  54. //REP(i,N){REP(j,M) cout<<A[i][j]<<' ';cout<<endl;}
  55. solve();
  56. cout<<ans1<<endl<<ans2<<endl;
  57. return 0;
  58. }

BZOJ1057 [ZJOI2007]棋盘制作 【最大同色矩形】的更多相关文章

  1. BZOJ1057 [ZJOI2007]棋盘制作(极大化思想)

    1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 1848  Solved: 936 [Submit][Sta ...

  2. BZOJ1057[ZJOI2007]棋盘制作 [单调栈]

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的 ...

  3. BZOJ1057 [ZJOI2007]棋盘制作

    Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源 于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应 ...

  4. 【单调栈 动态规划】bzoj1057: [ZJOI2007]棋盘制作

    好像还有个名字叫做“极大化”? Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源 于易经的思想,棋盘是一个8*8大小的黑白相间的 ...

  5. bzoj1057: [ZJOI2007]棋盘制作 [dp][单调栈]

    Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源 于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应 ...

  6. 洛谷 P1169||bzoj1057 [ZJOI2007]棋盘制作

    洛谷P1169 bzoj1057 这个题目跟最大全0子矩阵是类似的.正方形的话,只要把任意极大子正方形(”极大“定义见后面的”论文“)当成把某个极大子矩形去掉一块变成正方形即可,容易解决. 解法1:看 ...

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

    传送门 悬线法板题. 如果只求最大矩形面积那么跟玉蟾宫是一道题. 现在要求最大正方形面积. 所以每次更新最大矩形面积时用矩形宽的平方更新一下正方形答案就行了. 代码: #include<bits ...

  8. bzoj1057: [ZJOI2007]棋盘制作--最大子矩阵

    既然要求最大01子矩阵,那么把应该为0的位置上的数取反,这样就变成求最大子矩阵 最大子矩阵可以用单调栈 #include<stdio.h> #include<string.h> ...

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

    题目要求纵横坐标和奇偶性不同的点取值不同,于是我们把纵横坐标和奇偶性为1的点和0的点分别取反,就变成经典的最大全1子矩阵问题了,用悬线法解决. #include<iostream> #in ...

随机推荐

  1. python3 练习题100例 (二十六)回文数判断

    题目内容: 给一个5位数,判断它是不是回文数,是则输出yes,不是则输出no. 例如12321是回文数,它的个位与万位相同,十位与千位相同. 输入格式: 共一行,为一个5位数. 输出格式: 共一行,y ...

  2. Python系列5之模块

    模块 1. 模块的分类 模块,又称构件,是能够单独命名并独立地完成一定功能的程序语句的集合(即程序代码和数据结构的集合体). (1)自定义模块 自己定义的一些可以独立完成某个功能的一段程序语句,可以是 ...

  3. GDOI DAY1游记

    今天,是本蒟蒻的第一次参加GDOI,真激动! 今天,是GDOI第一天,昨天熬夜打代码,今天早上状态十分不好,于是... 进入了考场,叫我们自由打一会代码,于是...打了一坨AC机,重要的是错了(额.. ...

  4. C语言实例解析精粹学习笔记——33(扑克牌的结构表示)

    实例33: 使用“结构”定义一副扑克牌,并对变量赋值,输出结果 思路: 扑克牌有4种花色,用枚举类型表示花色,其他都是结构体的简单应用 程序代码: #include <stdio.h> # ...

  5. Eclipse报错:An internal error occurred during: "Building workspace". Java heap space),卡死解决办法

    在项目工程的根目录下,找到.project,用记事本打开,把两处删除掉: 第一处: <buildCommand> <name>org.eclipse.wst.jsdt.core ...

  6. c/c++指针传参

    首先要理解参数传递,参数传递分值传递,指针传递,引用传递.(就我自己理解,就是把实参对形参进行赋值) 值传递: 形参是实参的拷贝,改变形参的值并不会影响外部实参的值.从被调用函数的角度来说,值传递是单 ...

  7. 深度学习:激活函数的比较和优缺点,sigmoid,tanh,relu

    https://blog.csdn.net/u011684265/article/details/78039280

  8. Java检测端口的占用情况

    突然间想到这个问题,在网上搜了一下 http://blog.csdn.net/danieluk/article/details/18518175 网上有很多文章都是用上面那个方法来解决这个问题的,总感 ...

  9. 【APUE】Chapter16 Network IPC: Sockets & makefile写法学习

    16.1 Introduction Chapter15讲的是同一个machine之间不同进程的通信,这一章内容是不同machine之间通过network通信,切入点是socket. 16.2 Sock ...

  10. OpenCV入门:(二:加载,显示,修改以及保存图片)

    目标: 1.从图片文件打开图片(imread) 2.显示图片(namedWindow和imshow) 3.转换当前图片为灰色图片(cvtColor) 4.保存图片(imwrite) 代码: #incl ...