列表

详情


NC19900. [AHOI2014]拼图

描述

JYY最近迷上了拼图游戏。作为一个计算机科学家,JYY有一套黑白色的拼图,他希望通过合理的拼接,使得拼出的最终图案中,能包含面积最大的全白色子矩形。JYY一共有S块拼图,并且由1到S编号。编号为i的拼图是一个N行列的方格矩形,每个方格都为黑色或者白色。
一开始JYY将他的这S块拼图按照编号顺序左右相连依次放在桌上拼成了一个N行M列(这里M=Sigma(Wi)(1 ≤ i ≤ S)的大矩形。之后JYY发现,可以通过改变这S块拼图的连接次序,使得拼成的N行M列的大矩形中,最大全白子矩形面积变大。现在JYY想知道,怎么拼才能得到最大的全白子矩形呢?请你帮助他计算出最佳的拼接方案。

输入描述

每个输入文件中包含多组测试数据。
输入文件第一行包含一个整数T,代表测试数据的组数,接下来按顺序描述了每组测试数据。
每组测试数据的第一行包含两个整数S和N。
接下来S组输入,第i组对应编号为i的拼图。
在第i组输入中,第一行包含一个整数;
接下来N行描述一个N行列的0/1矩形;
其中第x行y列为0则表示该拼图对应位置的颜色是白色,反之则为黑色。

输出描述

对于每组数据输出一行包含一个整数ans,表示最大可能的全白色子矩形的面积。

示例1

输入:

1
3 4
4
1001
0000
0010
1001
3
000
010
000
011
2
00
10
01
00

输出:

6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 62ms, 内存消耗: 888K, 提交时间: 2019-03-16 14:05:10

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define LL long long
int read()
{
    int s=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
    return s*f;
}
int read2()
{
    int s=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';break;ch=getchar();}
    return s*f;
}
//smile please
int T,S,N,w[100005],ans;
bitset<100005> sa[405],pa;
int rr[405];
int main()
{
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    for(T=read();T--;)
       {S=read();N=read();ans=0;
        if(N<=300)
           {
            for(int i=1;i<=S;i++)
               {w[i]=read()+w[i-1];
                for(int j=1;j<=N;j++)
                    for(int k=w[i-1]+1;k<=w[i];k++)
                        sa[j][k]=read2();
               }
            for(int i=1;i<=N;i++)
               {pa=sa[i];
                for(int j=i;j<=N;j++)
                   {pa|=sa[j];
                    int sum=0,sum2=0;
                    int l1=0,lw1=0,l2=0;
                    int r1=0,rw1=0,r2=0;
                    for(int k=1;k<=w[S];k++)
                        sum=(pa[k]?0:sum+1),
                        ans=max(ans,(j-i+1)*sum);
                    for(int k=1;k<=S;k++)
                       {sum=0;
                        for(int l=w[k-1]+1;l<=w[k]&&!pa[l];l++)
                            sum++;
                        if(sum==w[k]-w[k-1])
                          {sum2+=w[k]-w[k-1];continue;}
                        if(sum>l1)
                          l2=l1,l1=sum,lw1=k;
                        else
                          if(sum>l2)
                            l2=sum;
                        sum=0;
                        for(int l=w[k];l>=w[k-1]+1&&!pa[l];l--)
                            sum++;
                        if(sum>r1)
                          r2=r1,r1=sum,rw1=k;
                        else
                          if(sum>r2)
                            r2=sum;
                       }
                    ans=max(ans,((lw1==rw1?max(l1+r2,l2+r1):l1+r1)+sum2)*(j-i+1));
                   }
               }
           }
        else
           {
            for(int i=1;i<=S;i++)
               {w[i]=read()+w[i-1];
                for(int j=1;j<=N;j++)
                    for(int k=w[i-1]+1;k<=w[i];k++)
                        sa[k][j]=read2();
               }
            for(int j=1;j<=w[S];j++)
                rr[j]=0;
            for(int i=N;i>=1;i--)
               {for(int j=1;j<=w[S];j++)
                    rr[j]=(sa[j][i]?0:rr[j]+1);
                for(int j=1;j<=w[S];j++)
                   {int sum=0,sum2=0;
                    int l1=0,lw1=0,l2=0;
                    int r1=0,rw1=0,r2=0;
                    for(int k=1;k<=w[S];k++)
                        sum=(rr[k]<rr[j]?0:sum+1),
                        ans=max(ans,rr[j]*sum);
                    for(int k=1;k<=S;k++)
                       {sum=0;
                        for(int l=w[k-1]+1;l<=w[k]&&rr[l]>=rr[j];l++)
                            sum++;
                        if(sum==w[k]-w[k-1])
                          {sum2+=w[k]-w[k-1];continue;}
                        if(sum>l1)
                          l2=l1,l1=sum,lw1=k;
                        else
                          if(sum>l2)
                            l2=sum;
                        sum=0;
                        for(int l=w[k];l>=w[k-1]+1&&rr[l]>=rr[j];l--)
                            sum++;
                        if(sum>r1)
                          r2=r1,r1=sum,rw1=k;
                        else
                          if(sum>r2)
                            r2=sum;
                       }
                    ans=max(ans,((lw1==rw1?max(l1+r2,l2+r1):l1+r1)+sum2)*rr[j]);
                   }
               }
           }
        printf("%d\n",ans);
       }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

上一题