hdu 1559 最大子矩阵

http://acm.hdu.edu.cn/showproblem.php?pid=1559

  汉语题,呵呵。

  思路:这个题跟我上一篇博文中的那个题的区别就在限制了子矩阵的大小。如果没有看过我上一篇博文的可以先去扫一眼,我们不妨回顾一下,那个题是怎么做的:我们采用了大家都比较熟知的,我自己习惯叫行压缩,我们新建了一个数组link来存放到当前行为止每一列的的和,这样就差不多回到一维的样子。那这个题又该怎么想呢?我们是不是可以采取每行的一部分,使得先满足子矩阵Y的要求,然后在限制列,使得满足子矩阵X的要求,是否可以呢?应该是可以的,但是当时我还有一点没有想通,我要怎么来限制X呢?这题最终解决是我在做完窗口移动那个题之后才想到这题X的限制完全可以用单调队列或者是双端队列来搞定。窗口移动那题,我会在我之后单调队列小结的博文中提到,希望大家关注我博客。

下面是代码:

View Code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#include <stack>

using namespace std;

const int maxn=1500;

int m,n,x,y,ma;
int num[maxn][maxn],link[maxn];
deque<int>d;
void data_in()
{
    scanf("%d %d %d %d",&m,&n,&x,&y);
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
            scanf("%d",&num[i][j]);
    }
}

inline int max(int x,int y)
{
    return x<y?y:x;
}

void cal()
{
    int ans=0,width=0;
    d.clear();
    for(int i=1;i<=n;i++)
    {
        ans+=link[i];
        width++;
        d.push_back(i);
        if(width==y)
        {
            ma=max(ma,ans);
            width--;
            ans-=link[d.front()];
            d.pop_front();
//            printf("%d\n",link[d.front()]);
        }
    }
}

void solve()
{
    ma=0;
    for(int i=1;i<=m-x+1;i++)
    {
        memset(link,0,sizeof(link));
        for(int j=i;j<i+x;j++)
        {
            for(int k=1;k<=n;k++)
                link[k]+=num[j][k];
        }
        cal();
    }
    printf("%d\n",ma);
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        data_in();
        solve();
    }
    return 0;
}

我代码中是先限制了X,才去用双端队列限制Y。跟之前思路有点出入,但是都无所谓,都可以做。

善待每一天,努力做好自己。

欢迎转载,注明出处。

原文地址:https://www.cnblogs.com/RainingDays/p/3067796.html