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

P1169 [ZJOI2007]棋盘制作

时间:2018-09-09 14:51:27      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:problem   std   长度   需要   log   str   内容   介绍   递推公式   

题目大意

给定一个01棋盘,求其中01交错的最大正方形与矩形。

解题思路:

其实是刚学悬线法来试试水

还有题解中别没有看太懂

发现很少有用悬线法的 所以介绍一下尝试水一篇题解

以下内容部分参考@Clove_unique

悬线法

用途:
   解决给定矩阵中满足条件的最大子矩阵
做法:
   用一条线(横竖貌似都行)左右移动直到不满足约束条件或者到达边界
 定义几个东西:
        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]

至于为什么递推公式中考虑上一层的情况?

是因为up数组的定义,up数组代表向上扩展最长长度,
所以需要考虑上一层的情况.

然后求解正方形&&长方形的情况即可。

题目要求01交错,所以"!="即可

-------------------代码-------------------

#include<bits/stdc++.h>
#define IL inline
#define RI register int
#define maxn 2001
IL void read(int &x){
    int f=1;x=0;char s=getchar();
    while(s>‘9‘||s<‘0‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s<=‘9‘&&s>=‘0‘){x=x*10+s-‘0‘;s=getchar();}
    x*=f;
}
int res[maxn][maxn],left[maxn][maxn],right[maxn][maxn],up[maxn][maxn];
int n,m,ans1,ans2;
int main()
{
    read(n),read(m);
    for(RI i=1;i<=n;i++)
        for(RI j=1;j<=m;j++)
            {
                read(res[i][j]);
                left[i][j]=right[i][j]=j;
                up[i][j]=1;
            }
    for(RI i=1;i<=n;i++)
        for(RI j=2;j<=m;j++)
            if(res[i][j]!=res[i][j-1])
                left[i][j]=left[i][j-1];//预处理左边界
    for(RI i=1;i<=n;i++)
        for(RI j=m-1;j>0;j--)
            if(res[i][j]!=res[i][j+1])
                right[i][j]=right[i][j+1];//预处理右边界
    for(RI i=1;i<=n;i++)
        for(RI j=1;j<=m;j++)
            {
                if(i>1&&res[i][j]!=res[i-1][j])
                {
                    left[i][j]=std::max(left[i][j],left[i-1][j]);
                    right[i][j]=std::min(right[i][j],right[i-1][j]);
                    up[i][j]=up[i-1][j]+1;
                }
                int a=right[i][j]-left[i][j]+1; //横向长度
                int b=std::min(a,up[i][j]);//竖向长度
                //printf("a:%d b:%d\n",a,b);
                ans1=std::max(ans1,b*b);//正方形
                ans2=std::max(ans2,a*up[i][j]);//长方形
            }
    printf("%d\n%d",ans1,ans2);
}

悬线法题目:P1169 棋盘制作 p4147 玉蟾宫 p2701 巨大的牛棚 p1387 最大正方形

P1169 [ZJOI2007]棋盘制作

标签:problem   std   长度   需要   log   str   内容   介绍   递推公式   

原文地址:https://www.cnblogs.com/-guz/p/9612810.html

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