最大(优)子矩阵问题合集 -- 持续更新

1.引进:

最近打算撸最大子矩阵这类问题,以后所有有关最大最优子矩阵的题目,都会补充道这里面。

嘛,这类问题还是挺有用处的,可以当做打牢基础的一些思维题目或者练习代码能力的题目来看,如有不对之处还请读者指出。哈哈吐舌头

2.题目参考:

奶牛浴场问题(极大化思想)


    参考博客

    这道题最重要的还是要想到每次都计算的极大有效子矩形这一点就可以优化成n^2了,其实自己多想想还是挺好理解的。
   吐舌头
   吐舌头
   吐舌头

    我起初这句话半天没看懂~,画图又想了很久之后终于解决了: 

    1.类似的,需要相应地修改上边界。以此类推,如果这个点是在当前点(确定左边界的点)上方,则修改上边界;如果在下方,则修改下边界;如果处在同一行,则可中止搜索(因为后面的矩形面积都是0了)。    一开始感觉有问题~ ~ ~   如果以此行为上边界或者写边界不可以吗???

    2.对于这种情况,可以用类似的方法从右到左扫描每一个点作为右边界的情况。

想想这两句话还是挺重要的,如果有哪里不懂可以指出来,我会的话可以给大家解答。

上代码:

#include<cstdio>
#include<cstdlib>
#define N 5010
#include<cstring>

int comp(const void*a,const void*b)//用来做比较的函数。
{
    return *(int*)a-*(int*)b;
}

int Fcomp(const void*a,const void*b)//用来做比较的函数。
{
    return *(int*)b-*(int*)a;
}

int L, W;
int n;
int miny, maxy;
int maxS;
int thisS;
int a[N][2];
int b[N][2];
int temp[N][2];
int main()
{


//    freopen("in.txt", "r", stdin);
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));

    scanf("%d%d", &L, &W);
    scanf("%d", &n);

    miny = 0;
    maxy = W;
    maxS = -1;
    thisS = 0;

    for(int i = 0; i < n; i ++)
    {
        scanf("%d%d", &a[i][0], &a[i][1]);
        b[i][0] = a[i][0];
        b[i][1] = a[i][1];
    }
    a[n][0] = L;
    a[n][1] = 0;

    a[n + 1][0] = 0;
    a[n + 1][1] = 0;

    a[n + 2][0] = 0;
    a[n + 2][1] = W;

    a[n + 3][0] = L;
    a[n + 3][1] = W;

    b[n][0] = L;
    b[n][1] = 0;

    b[n + 1][0] = 0;
    b[n + 1][1] = 0;

    b[n + 2][0] = 0;
    b[n + 2][1] = W;

    b[n + 3][0] = L;
    b[n + 3][1] = W;

    qsort(a[0], n + 4, sizeof(a[0]), comp);

//    for(int i = 0; i < n + 4; i ++)
//        printf("%d %d\n", a[i][0], a[i][1]);
//    printf("\n");
    for(int i = 0; i < n + 4; i ++)
    {
        miny = 0;
        maxy = W;

        for(int j = i + 1; j < n + 4; j ++)
        {
            thisS = (maxy - miny) * (a[j][0] - a[i][0]);
//            printf("+%d ", thisS);

            if(thisS > maxS)
                maxS = thisS;
            if(a[j][1] >= a[i][1] && a[j][1] <= maxy)
                maxy = a[j][1];
            if(a[j][1] <= a[i][1] && a[j][1] >= miny)
                miny = a[j][1];
            if(a[j][1] == a[i][1])
                break;
        }
    }

    for(int i = 0; i < n + 4; i ++)
    {
        temp[i][0] = b[i][0];
        b[i][0] = b[i][1];
        b[i][1] = temp[i][0];
    }
    qsort(b[0], n + 4, sizeof(b[0]), Fcomp);

    for(int i = 0; i < n + 4; i ++)
    {
        temp[i][0] = b[i][0];
        b[i][0] = b[i][1];
        b[i][1] = temp[i][0];
    }
//    for(int i = 0; i <= n; i ++)
//    {
//        printf("%d %d\n", b[i][0], b[i][1]);
//    }

    for(int i = 0; i < n + 4; i ++)   //整个矩形的左右边界为左右边界
    {
        thisS = L * (b[i][1] - b[i + 1][1]);
//        printf("%d*** ", thisS);

        if(thisS > maxS)
            maxS = thisS;
    }




    qsort(a[0], n + 4, sizeof(a[0]), comp);


    int ttx = 0;
    int tty = W;
    for(int i = n + 3; i >= 0; i --)
    {
        ttx = 0;
        tty = W;
        for(int j = i - 1; j >= 0; j --)
        {

            thisS = (tty - ttx) * (a[i][0] - a[j][0]);
//            printf("%d^%d^%d\n", tty - ttx, a[i][0] - a[j][0], thisS);

            if(thisS > maxS)
                maxS = thisS;
            if(a[j][1] > a[i][1] && a[j][1] < tty)
                tty = a[j][1];
            if(a[j][1] < a[i][1] && a[j][1] > ttx)
                ttx = a[j][1];
            if(a[j][1] == a[i][1])
                break;
        }
    }
    printf("%d", maxS);
}


吐舌头
吐舌头
吐舌头一个很有意思的博客地址,球球好玩,代码简洁。


悬线法

待更新。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值