码迷,mamicode.com
首页 > 其他好文 > 详细

【ZJOI2007】棋盘制作 - 悬线法

时间:2019-10-13 14:49:31      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:amp   int   main   cst   之一   决定   line   两种   世界   

题目描述

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

思路

本题用到的是悬线法
悬线法的用途:解决给定矩阵中满足条件的最大子矩阵
需要用到这几个东西
left[i][j]:代表从 (i,j) 能到达的最左位置
right[i][j]:代表从 (i,j) 能到达的最右位置
up[i][j]:代表从 (i,j) 向上扩展最长长度.
然后这样递推
left[i][j] = max(left[i][j],left[i-1][j])
right[i][j] = min(right[i][j],right[i-1][j])

代码

/************************************************
*Author        :  lrj124
*Created Time  :  2019.08.26.08:17
*Mail          :  1584634848@qq.com
*Problem       :  luogu1169
************************************************/
#include <algorithm>
#include <cstdio>
using std :: max;
using std :: min;
const int maxn = 2000 + 10;
int n,m,a[maxn][maxn],left[maxn][maxn],right[maxn][maxn],up[maxn][maxn],ans_sq,ans;
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]);
            up[i][j] = 1;
            left[i][j] = right[i][j] = j;
        }
    for (int i = 1;i <= n;i++)
        for (int j = 2;j <= m;j++)
            if (a[i][j] ^ a[i][j-1]) left[i][j] = left[i][j-1];
    for (int i = 1;i <= n;i++)
        for (int j = m-1;j;j--)
            if (a[i][j] ^ a[i][j+1]) right[i][j] = right[i][j+1];
    for (int i = 1;i <= n;i++)
        for (int j = 1,tmp;j <= m;j++) {
            if (i > 1 && a[i][j]^a[i-1][j]) {
                up[i][j] = up[i-1][j]+1;
                left[i][j] = max(left[i][j],left[i-1][j]);
                right[i][j] = min(right[i][j],right[i-1][j]);
            }
            tmp = right[i][j]-left[i][j]+1;
            ans = max(ans,tmp*up[i][j]);
            ans_sq = max(ans_sq,min(up[i][j],tmp)*min(up[i][j],tmp));
        }
    printf("%d\n%d",ans_sq,ans);
    return 0;
}

【ZJOI2007】棋盘制作 - 悬线法

标签:amp   int   main   cst   之一   决定   line   两种   世界   

原文地址:https://www.cnblogs.com/lrj124/p/11666368.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!