【思维】codeforces 1060 C. Maximum Subrectangle

版权声明:转载标注来源喔~ https://blog.csdn.net/iroy33/article/details/90047516

题意:矩阵c的每一项是由a和b对应项相乘得来的,问和不超过x的子矩阵中,最多有多少个元素?

思考:我贫瘠的智商让我只能想到暴力枚举对角线。看到博主sigh!这个图的时候我愣了

这个博主博客注册两年,原创842篇,不知道是直接从别的平台转移过来的还是现写的,伏地膜orz

思路:首先来分析一下这道题是不能用最大子矩阵(dp)的思路的,最大子矩阵问题求的是区间和最大,本题是要区间和<x,容量最大。从cij入手是不合适的,真正要考虑的是a的子段和与B的子段和。 暴力枚举出长度为len的最小子段和(因为要容量越大越好,值相同的情况下长度越大越好->相同长度下值越小越好),最后再暴力枚举矩阵的长宽得到答案

注意要开LL

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,x;
const int N=2e3+10;
const int INF=0x3f3f3f3f;
typedef long long LL;
LL a[N];
LL b[N];
LL suma[N];
LL sumb[N];
LL ma[N];          //长度为i时a数组的最小区间和
LL mb[N];          //长度为i时b数组的最小区间和
int ans=0;
int main()
{
    cin>>n>>m;
    suma[0]=0; sumb[0]=0;
    for(int i=1;i<=n;++i)
    {
        cin>>a[i];
        suma[i]=suma[i-1]+a[i];
    }
    for(int j=1;j<=m;++j)
    {
        cin>>b[j];
        sumb[j]=sumb[j-1]+b[j];
    }
    cin>>x;
    memset(ma,INF,sizeof(ma));
    memset(mb,INF,sizeof(mb));
    for(int len=1;len<=n;++len)
    {
        for(int i=1;i+len-1<=n;++i)
        {
            ma[len]=min(ma[len],suma[i+len-1]-suma[i-1]);

        }
    }
    for(int len=1;len<=m;++len)
    {
        for(int j=1;j+len-1<=m;++j)
        {
            mb[len]=min(mb[len],sumb[j+len-1]-sumb[j-1]);

        }
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
        {
            if(ma[i]*mb[j]<=x)
            {

                ans=max(ans,i*j);
            }
        }
    cout<<ans<<endl;
    return 0;


}

猜你喜欢

转载自blog.csdn.net/iroy33/article/details/90047516