bzoj1057: [ZJOI2007]棋盘制作(悬线法)

Posted Sakits

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1057: [ZJOI2007]棋盘制作(悬线法)相关的知识,希望对你有一定的参考价值。

  题目要求纵横坐标和奇偶性不同的点取值不同,于是我们把纵横坐标和奇偶性为1的点和0的点分别取反,就变成经典的最大全1子矩阵问题了,用悬线法解决。

技术分享
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int maxn=2010,inf=1e9;
int n,m,ans1,ans2;
int h[maxn],mp[maxn][maxn],l[maxn],r[maxn];
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<0||c>9)c==-&&(f=-1),c=getchar();
    while(c<=9&&c>=0)k=k*10+c-0,c=getchar();
    k*=f;                                                                                                                                                                        
}
int sqr(int x){return x*x;}
void dp()
{
    memset(h,0,(m+1)<<2);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        if(mp[i][j])h[j]++;else h[j]=0;
        for(int j=1;j<=m;j++)
        if(mp[i][j])
        for(l[j]=j;h[j]<=h[l[j]-1]&&mp[i][l[j]-1];l[j]=l[l[j]-1]);
        for(int j=m;j;j--)
        if(mp[i][j])
        for(r[j]=j;h[j]<=h[r[j]+1]&&mp[i][r[j]+1];r[j]=r[r[j]+1]);
        for(int j=1;j<=m;j++)
        ans1=max(ans1,(r[j]-l[j]+1)*h[j]);
        for(int j=1;j<=m;j++)
        ans2=max(ans2,min(sqr(r[j]-l[j]+1),sqr(h[j])));
    }
}
int main()
{
    read(n);read(m);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    read(mp[i][j]),mp[i][j]=((i+j)&1?mp[i][j]:!mp[i][j]);
    dp();
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)mp[i][j]=!mp[i][j];
    dp();
    printf("%d\n%d",ans2,ans1);
    
}
View Code

以上是关于bzoj1057: [ZJOI2007]棋盘制作(悬线法)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1057: [ZJOI2007]棋盘制作

Bzoj1057 [ZJOI2007]棋盘制作

BZOJ1057:[ZJOI2007]棋盘制作——题解

bzoj1057: [ZJOI2007]棋盘制作

bzoj 1057: [ZJOI2007]棋盘制作

bzoj1057 [ZJOI2007]棋盘制作