首页 > 代码库 > 1057: [ZJOI2007]棋盘制作
1057: [ZJOI2007]棋盘制作
1057: [ZJOI2007]棋盘制作
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 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
1 0 1
0 1 0
1 0 0
Sample Output
4
6
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("\n") 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 else122 {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 else139 {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\n",maxxx);158 printf("%d\n",maxx);159 }160 return 0;161 }
1057: [ZJOI2007]棋盘制作
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。