hdu 1081 1559 最大子矩阵

来源:互联网 发布:4g卡为什么显示3g网络 编辑:程序博客网 时间:2024/06/16 02:54

今天写了挺多最大子矩阵的题,以前有看过书,没搞懂什么叫
“枚举起始行和终止行后,把整个矩形压缩成一维的”
可能是脑子笨,现在看这句话很通俗易懂啊。
这里写图片描述

确定一个子矩阵就是要确定四个边界嘛,上下边用枚举的方法,求和时会省下很多不必要的计算,这道题还和昨天写的:http://poj.org/problem?id=3494有点像。
都用到了压缩行,把矩形压缩成一维的思想。

hdu 1081:

#include <iostream>#include <vector>#include <cstring>#include <algorithm>#include <stack>#include <cstdio>using namespace std;const int MAXN = 100 + 5;typedef long long ll;const int INF = 0x3f3f3f3f;int mat[MAXN][MAXN];int c[MAXN];int dp[MAXN];int point[2][2];int ans_point[2][2];int main() {    int n, m;    while (scanf("%d", &n) != EOF)    {        for (int i = 1; i <= n; ++i)            for (int j = 1; j <= n; ++j)                scanf("%d", &mat[i][j]);        int ans = -INF;        memset(point, 0, sizeof(point));        memset(ans_point, 0, sizeof(ans_point));        //枚举上下行        for (int i = 1; i <= n; ++i)        {            point[0][0] = i;    //左上的行数            for (int j = i; j <= n; ++j)            {                point[1][0] = j;    //右下的行数                for (int k = 1; k <= n; ++k)                    c[k] = i == j ? mat[i][k] : c[k] + mat[j][k];                memset(dp, 0, sizeof(dp));                int t = -INF;                int l = 1, r = 1;                point[0][1] = 1;    //左上的列数                for (int k = 1; k <= n; ++k)                {                    if (c[k] > dp[k - 1] + c[k])                    {                        dp[k] = c[k];                        l = r = k;                    }                    else                    {                        dp[k] = dp[k - 1] + c[k];                        r = k;                    }                    if (t < dp[k])                    {                        t = dp[k];                        point[0][1] = l;                        point[1][1] = r;                    }                }                if (t > ans)                {                    memcpy(ans_point, point, sizeof(point));                    ans = t;                }            }        }        printf("%d\n", ans);        /*for (int i = ans_point[0][0]; i <= ans_point[1][0]; ++i)        {        for (int j = ans_point[0][1]; j <= ans_point[1][1]; ++j)        printf("%d ", mat[i][j]);        printf("\n");        }*/    }    return 0;}

hdu 1559:

#include <iostream>#include <vector>#include <cstring>#include <algorithm>#include <stack>#include <cstdio>#define max(a, b) ((a) > (b) ? (a) : (b))using namespace std;const int MAXN = 1000 + 5;typedef long long ll;const int INF = 0x3f3f3f3f;int mat[MAXN][MAXN];int c[MAXN];int main() {    int n, m, x, y, T;    scanf("%d", &T);    while (T--)    {        scanf("%d %d %d %d", &n, &m, &x, &y);        for (int i = 1; i <= n; ++i)            for (int j = 1; j <= m; ++j)                scanf("%d", &mat[i][j]);        int ans = -INF;        //枚举上下行        for (int i = 1; i <= n - x + 1; ++i)        {            for (int j = i; j <= n; ++j)            {                for (int k = 1; k <= m; ++k)                    c[k] = i == j ? mat[i][k] : c[k] + mat[j][k];                if (j - i + 1 < x)                    continue;                int t = 0;                for (int k = 1; k <= y; ++k)                    t += c[k];                ans = max(ans, t);                for (int k = y + 1; k <= m; ++k)                {                    t = t + c[k] - c[k - y];                    ans = max(ans, t);                }                break;            }        }        printf("%d\n", ans);    }    return 0;}
原创粉丝点击