luogu 2331

给出 $n * 1$ 的矩阵,选出 $k$ 个互不重叠的子矩阵,使得其最大
$sum[i]$ 为列的前缀和
设 $f[i][j]$ 表示前 $i$ 个数选出 $j$ 个互不重叠的子矩阵的最大价值
若第 $i$ 个数不属于第 $j$ 个矩阵 $f[i][j] = f[i - 1][j]$
否则枚举第 $j$ 个矩阵的起点 $s$,$f[i][j] = max(f[i][j], f[s - 1][j - 1] + sum[i] - sum[s - 1])$

给出 $n * 2$ 的矩阵,选出 $k$ 个互不重叠的子矩阵,使得其最大
$sum[i][1]$ 为列 $1$ 的前缀和
$sum[i][2]$ 为列 $2$ 的前缀和
$f[i][j][use]$ 表示第 $1$ 列选到的 $i$ 行,第 $2$ 列选到了 $j$ 行,选了 $use$ 个矩阵的最大价值和
考虑枚举 $i, j, use$
第 $i$ 行第 $1$ 列不属于子矩阵或第 $j$ 行第 $2$ 列不属于子矩阵
$f[i][j][use] = std:: max(f[i - 1][j][use], f[i][j - 1][use])$
第 $i$ 行第 $1$ 列和第 $j$ 行第 $2$ 列属于不同的子矩阵
分别枚举第 $i$ 行第 $1$ 列所在子矩阵的起始点和第 $j$ 行第 $2$ 列所在子矩阵的起始点并更新答案,

$f[i][j][use] = max (f[i][j][use], max(f[h-1][j][l-1]+(sum1[i]-sum1[h-1]), 1<=h<=i))$
$f[i][j][use] = max (f[i][j][use], max(f[i][h-1][l-1]+(sum2[j]-sum2[h-1]),1<=h<=j))$

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

#define gc getchar()

inline int read() {
    int x = 0, ff = 1;
    char c = gc;
    while(c < '0' || c > '9') {if(c == '-') ff = -1; c = gc;}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x * ff;
}

const int N = 110;

int f[N][N][15], sum[N][N], n, m, k, A[N][N];

int main() {
    n = read(), m = read(), k = read();
    for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) A[i][j] = read();
    if(m == 1) {
        for(int i = 1; i <= n; i ++) sum[i][0] = sum[i - 1][0] + A[i][1];
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= k; j ++) {
                f[i][j][0] = f[i - 1][j][0];
                for(int s = 1; s <= i; s ++) f[i][j][0] = std:: max(f[i][j][0], f[s - 1][j - 1][0] + sum[i][0] - sum[s - 1][0]);
            }
        std:: cout << f[n][k][0];
    } else {
        for(int i = 1; i <= n; i ++) sum[i][1] = sum[i - 1][1] + A[i][1];
        for(int i = 1; i <= n; i ++) sum[i][2] = sum[i - 1][2] + A[i][2];
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                for(int use = 1; use <= k; use ++) {
                    f[i][j][use] = std:: max(f[i - 1][j][use], f[i][j - 1][use]);
                    for(int s = 1; s <= i; s ++) f[i][j][use] = std:: max(f[i][j][use], f[s - 1][j][use - 1] + (sum[i][1] - sum[s - 1][1]));
                    for(int s = 1; s <= j; s ++) f[i][j][use] = std:: max(f[i][j][use], f[i][s - 1][use - 1] + (sum[j][2] - sum[s - 1][2]));
                    if(i == j)
                        for(int s = 1; s <= i; s ++)
                            f[i][j][use] = std:: max(f[i][j][use], f[s - 1][s - 1][use - 1] + (sum[i][1] - sum[s - 1][1]) + (sum[i][2] - sum[s - 1][2]));
                }
        std:: cout << f[n][n][k];
    }
    return 0;
}

 

posted @ 2018-08-13 14:55  xayata  阅读(100)  评论(0编辑  收藏  举报