bzoj 1057: [ZJOI2007]棋盘制作

首先是对于图上所有的棋盘一定属于以下两种类型:

1.黑格行列奇偶性相同,白格不同

2.白格行列奇偶性相同,黑格不同

那么在输入的时候属于第一种情况的赋1,属于第二种情况的赋0

统计最大的1或0矩形和正方形就可以啦。

统计矩形和玉蟾宫是一样的做法,单调栈嘛。

 1 #include <cstdio>
 2 #include <stack>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm> 
 6 using namespace std;
 7 #define N 2008
 8 
 9 int ans1,ans2,n,m,f[N][N],s[N],w[N],top;
10 bool map[N][N];
11 
12 void build()
13 {
14     scanf("%d%d",&n,&m);
15     for (int i = 1;i <= n;i++)
16         for (int j = 1;j <= m;j++)
17         {   
18             int a; scanf("%d",&a);
19             if ((i & 1) == (j & 1) && a || (i & 1) != (j & 1) && !a) map[i][j] = 1;//& 优先级低于 ==!! 
20             else map[i][j] = 0;
21         }
22     for (int i = 1;i <= n;i++)
23         for (int j = 1;j <= m;j++)
24             if (map[i][j]) f[i][j] = f[i][j-1] + 1;
25             else f[i][j] = 0;
26 }
27 
28 void rebuild()
29 {
30     for (int i = 1;i <= n;i++)
31         for (int j = 1;j <= m;j++)
32 //            map[i][j] = ~map[i][j]; 不能按位取反!!因为第一位之后的也会取反!!
33             map[i][j] = !map[i][j];  
34     for (int i = 1;i <= n;i++)
35         for (int j = 1;j <= m;j++)
36             if (map[i][j]) f[i][j] = f[i][j-1] + 1;
37             else f[i][j] = 0;
38 }
39 
40 inline int sqr(int a)
41     {return (a*a);}
42     
43 void work()
44 {
45     for (int j = 1;j <= m;j++)
46     {
47         top = 0;
48         for (int i = 1;i <= n + 1;i++)
49         {
50             int minw = i;
51             while (top && s[top] >= f[i][j])
52             {
53                 ans1 = max(ans1,s[top] * (i - w[top]));
54                 ans2 = max(ans2,sqr(min(s[top],i-w[top])));
55                 minw = w[top];
56                 top--;
57             }
58             s[++top] = f[i][j]; w[top] = minw;
59         }
60     }
61 }
62 
63 void makeline()
64 {for (int i = 1;i <= m;i++) printf("--");printf("\n");}
65 
66 void debug()
67 {
68     makeline();
69     for (int i = 1;i <= n;i++)
70     {
71         for (int j = 1;j <= m;j++) printf("%d ",map[i][j]);
72         printf("\n");
73     }
74     makeline();
75     for (int i = 1;i <= n;i++)
76     {
77         for (int j = 1;j <= m;j++) printf("%d ",f[i][j]);
78         printf("\n");
79     }
80 }
81 
82 int main()
83 {
84 //    freopen("input.txt","r",stdin);
85     build();
86 //    debug();
87     work();
88     rebuild();
89 //    debug();
90     work();
91     printf("%d\n%d\n",ans2,ans1);
92     return 0;
93 }
View Code

 

posted @ 2014-01-22 10:45  乌拉拉979  阅读(...)  评论(... 编辑 收藏