UVa108 UVa10827 最大连续子矩阵和

UVa 108
题意:
求最大连续子矩阵和
分析:
类似于一维求前缀和一样,用sum[i][j]求一下以(i,j)为右下角端点的矩形的和,然后枚举矩阵的y轴的上下边界,然后扫一遍x轴,找到最小的前缀子矩形,然后当前矩形和sum[i][k] - sum[j][k]减去最小的就是最大的。

const int N = 100 + 9;
int a[N][N], sum[N][N], r[N], n;
int main() {
    //freopen("f.txt","r",stdin);
    while (~scanf ("%d", &n) ) {

        memset (sum, 0, sizeof (sum) );
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++) {
                scanf ("%d", &a[i][j]);
                sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
            }
        int ans = -INF;
        for (int i = 1; i <= n; i++) //上边界
            for (int j = 0; j < i; j++) { //下边界
                int minn = 0;
                for (int k = 1; k <= n; k++) {
                    int t = sum[i][k] - sum[j][k] - minn;
                    if (t > ans) ans = t;
                    if (minn > sum[i][k] - sum[j][k]) minn = sum[i][k] - sum[j][k];
                }
            }
        printf ("%d\n", ans);
    }
    return 0;
}

UVa10827
题意:
求环面上最大连续子矩阵和
分析:
这题是上题的进阶版,因为给出的矩阵是球形的,所以不难想到倍增什么的,所以每一行增加一倍,每一列也增加一倍,构成2N*2N的矩阵,然后我们只要求一下最大边长是N的最大连续子矩阵就好了。
因为最大边长是N,所以我们枚举左上角坐标和矩形的长宽,然后维护最大子矩阵和即可。

const int N = 75 * 2 + 9;
int a[N][N], sum[N], r[N], n;
int main() {
    //freopen("f.txt","r",stdin);
    int T;
    scanf ("%d", &T);
    while (T--) {
        scanf ("%d", &n);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++) {
                scanf ("%d", &a[i][j]);
                a[i][j + n] = a[i + n][j] = a[i + n][j + n] = a[i][j]; //扩展矩阵
            }
        int ans = -INF;
        for (int i = 0; i < n; i++) //左上角横坐标
            for (int j = 0; j < n; j++) //纵坐标
                for (int l = 0; l < n; l++) //长(列)
                    for (int w = 0; w < n; w++) { //宽(行)
                        r[w] = a[i + l][j + w]; //第w行的和
                        if (w) r[w] += r[w - 1];
                        if (l) sum[w] += r[w];
                        else sum[w] = r[w];
                        if (ans < sum[w]) ans = sum[w];
                    }
        printf ("%d\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值