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

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

时间:2017-09-07 20:18:11      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:hid   解决   size   不同   ios   取反   har   悬线法   class   

  题目要求纵横坐标和奇偶性不同的点取值不同,于是我们把纵横坐标和奇偶性为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]棋盘制作(悬线法)

标签:hid   解决   size   不同   ios   取反   har   悬线法   class   

原文地址:http://www.cnblogs.com/Sakits/p/7491487.html

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