UPC3463: Maximal-sum Subsequence

题目描述

给一个 N×N 的矩阵 M,可以取连续的一段数(必须是横着或者竖着或者斜着,这个矩阵是循环的,具体如下)。要求找到一个子序列,使得这个序列的和最大。

对于 N=8 的矩阵,如下序列都是合法的:
    M2,1,M2,2,M2,3,M2,4,M2,5,M2,6,M2,7,M2,8.
    M2,2,M2,3,M2,4.
    M2,6,M2,7,M2,8,M2,1,M2,2.
    M4,3,M5,3,M6,3,M7,3.
    M1,2,M2,3,M3,4,M4,5.
    M2,4,M3,3,M4,2,M5,1.
    M3,3,M4,2,M5,1,M1,5.
    M5,6.
一个元素不可取多次,取的必须是连续的一段。
可以什么都不取(即答案为 0)。
 

输入

第一行一个数 T (T≤30),表示数据组数。
每一组数据第一行为一个正整数 N (1≤N≤1000)。
接下来 N 行每行 N 个数表示这个矩阵。(每个元素大小在 −32768 到 32767 之间)

输出

每组数据一行表示最大的序列和。

样例输入

1
4 
8 6 6 1
-3 4 0 5
4 2 1 9
1 -9 9 -2

样例输出

24

提示

样例解释:选取序列 M3,4,M4,3,M1,2。

 
循环数组最大子串和=max(数组和+元素取反后最大子串和,原数组最大子串和)
然后对横、竖、从左上到右下,从左下到右上的所有结果取最大值
 
#include "bits/stdc++.h"

using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 1100;
int a[maxn][maxn], b[maxn][maxn];
int n;
int f1[maxn], f2[maxn];
int ans;

int main() {
    freopen("input.txt", "r", stdin);
    int _;
    scanf("%d", &_);
    while (_--) {
        scanf("%d", &n);
        ans = -inf;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                scanf("%d", &a[i][j]);
                b[i][j] = -a[i][j];
            }
        }
        int sum, max1, max2;
        for (int i = 1; i <= n; i++) {
            sum = 0, max1 = -inf, max2 = -inf;//max2为取反后最大子串和
            for (int j = 1; j <= n; j++) {
                sum += a[i][j];
                f1[j] = 0;
                f2[j] = 0;
            }
            for (int j = 1; j <= n; j++) {
                if (f1[j - 1] >= 0) {
                    f1[j] = f1[j - 1] + a[i][j];
                } else
                    f1[j] = a[i][j];
                if (f2[j - 1] >= 0) {
                    f2[j] = f2[j - 1] + b[i][j];
                } else f2[j] = b[i][j];
                max1 = max(max1, f1[j]);
                max2 = max(max2, f2[j]);

            }
            ans = max(ans, max(sum + max2, max1));

            sum = 0, max1 = -inf, max2 = -inf;
            for (int j = 1; j <= n; j++) {
                sum += a[j][i];
                f1[j] = 0;
                f2[j] = 0;
            }
            for (int j = 1; j <= n; j++) {
                if (f1[j - 1] >= 0) {
                    f1[j] = f1[j - 1] + a[j][i];
                } else
                    f1[j] = a[j][i];
                if (f2[j - 1] >= 0) {
                    f2[j] = f2[j - 1] + b[j][i];
                } else
                    f2[j] = b[j][i];
                max1 = max(max1, f1[j]);
                max2 = max(max2, f2[j]);
            }
            ans = max(ans, max(sum + max2, max1));

            sum = 0, max1 = -inf, max2 = -inf;
            for (int j = 1; j <= n; j++) {
                sum += a[j][(j + i - 1) % n + 1];
                f1[j] = 0;
                f2[j] = 0;
            }
            for (int j = 1; j <= n; j++) {
                if (f1[j - 1] >= 0) {
                    f1[j] = f1[j - 1] + a[j][(j + i - 1) % n + 1];
                } else
                    f1[j] = a[j][(j + i - 1) % n + 1];
                if (f2[j - 1] >= 0) {
                    f2[j] = f2[j - 1] + b[j][(j + i - 1) % n + 1];
                } else
                    f2[j] = b[j][(j + i - 1) % n + 1];
                max1 = max(max1, f1[j]);
                max2 = max(max2, f2[j]);
            }
            ans = max(ans, max(sum + max2, max1));

            sum = 0, max1 = -inf, max2 = -inf;
            int t;

            for (int j = 1; j <= n; j++) {
                t = (n - j - 1 + n) % n + 1;
                sum += a[t][(j - i - 1 + n) % n + 1];
                f1[j] = 0;
                f2[j] = 0;
            }
            for (int j = 1; j <= n; j++) {
                t = (n - j - 1 + n) % n + 1;
                if (f1[j - 1] >= 0) {
                    f1[j] = f1[j - 1] + a[t][(j - i - 1 + n) % n + 1];
                } else
                    f1[j] = a[t][(j - i - 1 + n) % n + 1];
                if (f2[j - 1] >= 0) {
                    f2[j] = f2[j - 1] + b[t][(j - i - 1 + n) % n + 1];
                } else
                    f2[j] = b[t][(j - i - 1 + n) % n + 1];
                max1 = max(max1, f1[j]);
                max2 = max(max2, f2[j]);
            }
            ans = max(ans, max(sum + max2, max1));
        }

        if (ans < 0) ans = 0;
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/albert-biu/p/10339716.html