zoukankan      html  css  js  c++  java
  • luogu 1169 棋盘制作(单调栈/悬线)

    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
    %d", ans2, ans1);
        return 0;
    }
    
  • 相关阅读:
    java.lang.IllegalAccessError: tried to access method org.apache.poi.util.POILogger.log from class org.apache.poi.openxml4j.opc.ZipPackage
    相同域名不同端口的两个应用,cookie名字、路径都相同的情况下,后面cookie会覆盖前面cookie吗
    power designer 连接mysql提示“connection test failed”
    疑问:Spring 中构造器、init-method、@PostConstruct、afterPropertiesSet 孰先孰后,自动注入发生时间
    intelj idea 创建聚合项目(典型web项目,包括子项目util、dao、service)
    Mysql启动时提示:Another MySQL daemon already running with the same unix socket.
    MySql中的varchar长度究竟是字节还是字符
    百度echarts使用--y轴label数字太长难以全部显示
    记录项目中用的laypage分页代码
    Ubuntu16.04下安装Cmake-3.8.2并为其配置环境变量
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/8445729.html
Copyright © 2011-2022 走看看