luogu 1169 棋盘制作(单调栈/悬线)

国际象棋是世界上最古老的博弈游戏之一,和中国的围棋、象棋以及日本的将棋同享盛名。据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳。而我们的主人公小Q,正是国际象棋的狂热爱好者。作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则。小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。不过小Q还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。于是小Q找到了即将参加全国信息学竞赛的你,你能帮助他么?N, M ≤ 2000。

首先,一个是棋盘的矩阵,满足相邻两个元素颜色不同。假设左上角的(1,1)是白色的格子。那么易证,横纵坐标之和是偶数的格子是白色的,是奇数的各自是黑色的。所以逆向思维,只要把给定的矩阵,横纵坐标之和同模2的一种格子反色,问题就变成了求最大的同色矩阵和同色正方形。这是最大子矩阵问题。用单调栈可以做,不过比悬线法烦一些。下面我来介绍一下悬线法。

悬线就是一端贴着不可算入矩形的区域(墙壁)的线。首先,一个最大子矩阵中一定有悬线,不然这个矩阵是可以再扩张的。所以,我们只要枚举所有悬线即可。首先n^2预处理出每个点向上向下能扩展的最大距离。然后从左向右,从右向左分别枚举一遍所有悬线(横向的),找出最大值即可。详见代码。

还有,个人感觉这种题目的思路很重要,就是把求最优解,转化为求出每个元素作为基础的最优值,然后取最优值中的最优值作为答案。

#include <cstdio>
using namespace std; const int maxn=2005, INF=1e9;\
typedef int inta2[maxn][maxn]; int n, m, ans1, ans2, begin, minup, mindown;
inta2 a, up, down; int max(int x, int y){ return x<y?y:x; }
int min(int x, int y){ return x<y?x:y; }
int sqr(int x){ return x*x; } int main(){
scanf("%d%d", &n, &m);
for (int i=1; i<=n; ++i) //转换棋盘
for (int j=1; j<=m; ++j){
scanf("%d", &a[i][j]);
if (i&1) a[i][j]^=1;
if (!(j&1)) a[i][j]^=1;
}
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
up[i][j]=(a[i][j]==a[i-1][j]?
up[i-1][j]+1:1);
for (int i=n; i>0; --i)
for (int j=1; j<=m; ++j)
down[i][j]=(a[i][j]==a[i+1][j]?
down[i+1][j]+1:1);
//悬线法
for (int color=0; color<=1; ++color)
for (int i=1; i<=n; ++i){
minup=mindown=INF; begin=1;
for (int j=1; j<=m; ++j){
if (a[i][j]!=color){
minup=mindown=INF;
begin=j+1; continue;
}
minup=min(minup, up[i][j]);
mindown=min(mindown, down[i][j]);
ans1=max(ans1, (minup+mindown-1)*(j-begin+1));
ans2=max(ans2, sqr(min(minup+mindown-1, j-begin+1)));
}
minup=mindown=INF; begin=m;
for (int j=m; j>0; --j){
if (a[i][j]!=color){
minup=mindown=INF;
begin=j-1; continue;
}
minup=min(minup, up[i][j]);
mindown=min(mindown, down[i][j]);
ans1=max(ans1, (minup+mindown-1)*(begin-j+1));
ans2=max(ans2, sqr(min(minup+mindown-1, begin-j+1)));
}
}
printf("%d\n%d", ans2, ans1);
return 0;
}

luogu 1169 棋盘制作(单调栈/悬线)的更多相关文章

  1. 洛谷P4147 玉蟾宫 单调栈/悬线法

    正解:单调栈/悬线法 解题报告: ummm这题我当初做的时候一点思路也没有只会暴力出奇迹:D(啊听说暴力好像能水过去呢,,, 然后当初是看的题解,然后学了下悬线法 然后就忘了:D 然后我现在看发现看不 ...

  2. bzoj 1057: [ZJOI2007]棋盘制作 单调栈

    题目链接 1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 2027  Solved: 1019[Submit] ...

  3. [ZJOI2007]棋盘制作 (单调栈)

    [ZJOI2007]棋盘制作 题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间 ...

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

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

  5. [洛谷P1169] [ZJOI2007] 棋盘制作 解题报告(悬线法+最大正方形)

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

  6. [ZJOI2007]棋盘制作 (单调栈,动态规划)

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

  7. luogu1169 棋盘制作 (单调栈)

    先预处理出来从每个位置 以0开始 往右交替最多能放多少格 然后就相当于对每一列做HISTOGRA #include<bits/stdc++.h> #define pa pair<in ...

  8. luogu 3467 [POI2008]PLA-Postering 单调栈

    题目描述: Description N个矩形,排成一排. 现在希望用尽量少的矩形海报Cover住它们. Input 第一行给出数字N,代表有N个矩形.N在[1,250000] 下面N行,每行给出矩形的 ...

  9. [P1169] 棋盘制作 &悬线法学习笔记

    学习笔记 悬线法 最大子矩阵问题: 在一个给定的矩形中有一些障碍点,找出内部不包含障碍点的,边与整个矩形平行或重合的最大子矩形. 极大子矩型:无法再向外拓展的有效子矩形 最大子矩型:最大的一个有效子矩 ...

随机推荐

  1. 【python】使用python写windows服务

    背景 运维windows服务器的同学都知道,windows服务器进行批量管理的时候非常麻烦,没有比较顺手的工具,虽然saltstack和ansible都能够支持windows操作,但是使用起来总感觉不 ...

  2. 微信小程序开发:学习笔记[7]——理解小程序的宿主环境

    微信小程序开发:学习笔记[7]——理解小程序的宿主环境 渲染层与逻辑层 小程序的运行环境分成渲染层和逻辑层. 程序构造器

  3. 多线程(三) iOS中的锁

    锁的类别:互斥锁,递归锁,条件锁,自旋锁等 锁的实现方式:NSLock,NSRecursiveLock, NSConditionLock,@synchronized,GCD的信号量等 下面说一下常用的 ...

  4. Contiki Process概述

    本文涉及到的Protothread机制知识,在http://www.cnblogs.com/songdechiu/p/5793717.html 一.进程类型 进程类型主要有协同式(cooperativ ...

  5. 在EditText插入表情,并发送表情

    在EditText插入表情,点击发送按钮,将qq表情显示在TextView中: [mw_shl_code=java,true]public class EditTextActivity extends ...

  6. ZOJ 3640 Help Me Escape:期望dp

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3640 题意: 有一个吸血鬼被困住了,他要逃跑... 他面前有n条 ...

  7. Java微信公众平台开发_03_消息管理之被动回复消息

    GitHub源码:https://github.com/shirayner/weixin_gz 一.本节要点 1.回调url 上一节,我们启用服务器配置的时候,填写了一个服务器地址(url),如下图, ...

  8. 使用js获取当前页面的url网址信息。

    1.设置或获取整个 URL 为字符串: window.location.href 2.设置或获取与 URL 关联的端口号码: window.location.port 3.设置或获取 URL 的协议部 ...

  9. 一个关于前端页面的小标签<tbody>

    我们有时候希望将表格的内容分为多个模块,这时候就可以使用<tbody>标签,它是<table>的字标签,是<tr>的父标签,可以使用它达到一种设置样式的结果.

  10. 使用OGNL表达式

    OGNL表达式(#号的用法) 用法1:访问OGNL上下文和Action上下文,#相当于ActionContext.getContext() 1.如果访问其他Context中的对象,由于他们不是根对象, ...