BZOJ 1057 悬线法求最大01矩阵

1057: [ZJOI2007]棋盘制作

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

Sample Output

4
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 }

 

转载于:https://www.cnblogs.com/BIGTOM/p/10351688.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值