1057: [ZJOI2007]棋盘制作

1057: [ZJOI2007]棋盘制作

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 2398  Solved: 1191
[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

思路:单调栈;

只要将(i+j)%2==0,的方格反转下,就转变为求最大子矩阵的问题,用单调栈维护下就行,复杂度(n*m);

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<queue>
  6 #include<deque>
  7 #include<stack>
  8 #include<math.h>
  9 using namespace std;
 10 int ma[3000][3000];
 11 int a[3000][3000];
 12 int b[3000][3000];
 13 stack<int>stac;
 14 int R[3000];
 15 int L[3000];
 16 int main(void)
 17 {
 18     int n,m;
 19     int i,j;
 20     scanf("%d %d",&n,&m);
 21     {
 22         memset(a,0,sizeof(a));
 23         memset(b,0,sizeof(b));
 24         for(i = 1; i <= n; i++)
 25         {
 26             for(j = 1; j <= m; j++)
 27             {
 28                 scanf("%d",&ma[i][j]);
 29             }
 30         }
 31         for(i = 1; i <= n; i++)
 32         {
 33             for(j = 1; j <= m; j++)
 34             {
 35                 if((i+j)%2)
 36                 {
 37                     ma[i][j]+=1;
 38                     ma[i][j]%=2;
 39                 }
 40                 //printf("%d ",ma[i][j]);
 41             }//printf("
")
 42         }
 43         for(i = 1; i <= n; i++)
 44         {
 45             for(j = 1; j <= m; j++)
 46             {
 47                 if(ma[i][j])
 48                 {
 49                     a[i][j] = a[i][j-1]+1;
 50                 }
 51                 if(!ma[i][j])
 52                 {
 53                     b[i][j] = b[i][j-1]+1;
 54                 }
 55             }
 56         }
 57         int maxx = 0;
 58         int maxxx = 0;
 59         for(j = 1; j <= m; j++)
 60         {
 61             while(!stac.empty())
 62             {
 63                 stac.pop();
 64             }
 65             for(i = 1; i <= n; i++)
 66             {
 67                 if(stac.empty())
 68                 {
 69                     L[i] = 1;
 70                     stac.push(i);
 71                 }
 72                 else
 73                 {
 74                     while(!stac.empty())
 75                     {
 76                         int x = stac.top();
 77                         if(a[i][j] < a[x][j])
 78                         {
 79                             R[x] = i-1;
 80                             stac.pop();
 81                         }
 82                         else break;
 83                     }
 84                     if(stac.empty())
 85                     {
 86                         L[i] = 1;
 87                         stac.push(i);
 88                     }
 89                     else
 90                     {
 91                         L[i] = stac.top()+1;
 92                         stac.push(i);
 93                     }
 94                 }
 95             }
 96             while(!stac.empty())
 97             {
 98                 int x= stac.top();
 99                 stac.pop();
100                 R[x] = n;
101             }
102             for(i = 1; i <= n; i++)
103             {
104                 maxx = max(maxx,(R[i]-L[i]+1)*a[i][j]);
105                 maxxx = max(maxxx,min((R[i]-L[i]+1),a[i][j])*min((R[i]-L[i]+1),a[i][j]));
106             }
107         }
108         for(j = 1; j <= m; j++)
109         {
110             while(!stac.empty())
111             {
112                 stac.pop();
113             }
114             for(i = 1; i <= n; i++)
115             {
116                 if(stac.empty())
117                 {
118                     L[i] = 1;
119                     stac.push(i);
120                 }
121                 else
122                 {
123                     while(!stac.empty())
124                     {
125                         int x = stac.top();
126                         if(b[i][j] <= b[x][j])
127                         {
128                             R[x] = i-1;
129                             stac.pop();
130                         }
131                         else break;
132                     }
133                     if(stac.empty())
134                     {
135                         L[i] = 1;
136                         stac.push(i);
137                     }
138                     else
139                     {
140                         L[i] = stac.top()+1;
141                         stac.push(i);
142                     }
143                 }
144             }
145             while(!stac.empty())
146             {
147                 int x= stac.top();
148                 stac.pop();
149                 R[x] = n;
150             }
151             for(i = 1; i <= n; i++)
152             {
153                 maxx = max(maxx,(R[i]-L[i]+1)*b[i][j]);
154                 maxxx = max(maxxx,min((R[i]-L[i]+1),b[i][j])*min((R[i]-L[i]+1),b[i][j]));
155             }
156         }
157         printf("%d
",maxxx);
158         printf("%d
",maxx);
159     }
160     return 0;
161 }
原文地址:https://www.cnblogs.com/zzuli2sjy/p/5941697.html