bzoj1084_最大子矩阵_SCOI2005_dp

123 篇文章 0 订阅

题目描述


这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。

输入格式:


第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。

输出格式:


只有一行为k个子矩阵分值之和最大为多少。

Analysis


仔细阅读题目后我们发现 1m2 1 ≤ m ≤ 2
这说明什么?我们可以把它强行拆分成两条链来做,于是乎题目变成在序列中取出k组数的最大值
f[i][j] f [ i ] [ j ] 表示前i项分j组的最大值,那么 f[i][j]=f[k][j]+sum[k+1][j]   (1ki) f [ i ] [ j ] = f [ k ] [ j ] + s u m [ k + 1 ] [ j ]       ( 1 ≤ k ≤ i )
二维的可以自己想一下,不难的
我会说我根本没有写判断直接就A了?

Code


#include <stdio.h>
#include <string.h>
#define rep(i, a, b) for (int i = a; i <= b; i ++)
#define fill(x, t) memset(x, t , sizeof(x))
#define N 101
#define K 11
using namespace std;
int f[N][N][K], num[N][3], s[N][3];
inline int read(){
    int x = 0, v = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-'){
            v = -1;
        }
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0'){
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x * v;
}
inline int max(int x, int y){
    return x<y?y:x;
}
inline int min(int x, int y){
    return x<y?x:y;
}
inline int sum(int x, int y, int v){
    int tmp1 = s[y][1] - s[x - 1][1];
    int tmp2 = s[y][2] - s[x - 1][2];
    if (v == 1){
        return tmp1;
    }else if (v == 2){
        return tmp2;
    }else{
        return tmp1 + tmp2;
    }
}
int main(void){
    int n = read(), m = read(), p = read();
    rep(i, 1, n){
        rep(j, 1, m){
            num[i][j] = read();
            s[i][j] = s[i - 1][j] + num[i][j];
        }
    }
    rep(i, 1, n){
        rep(j, 1, n){
            rep(k, 1, p){
                f[i][j][k] = max(f[i - 1][j][k], f[i][j - 1][k]);
                rep(l, 1, i){
                    f[i][j][k] = max(f[i][j][k], f[l - 1][j][k - 1] + sum(l, i, 1));
                }
                rep(l, 1, j){
                    f[i][j][k] = max(f[i][j][k], f[i][l - 1][k - 1] + sum(l, j, 2));
                }
                rep(l, 1, min(i, j)){
                    f[i][j][k] = max(f[i][j][k], f[l - 1][l - 1][k - 1] + sum(l, min(i, j), 3));
                }
            }
        }
    }
    printf("%d\n", max(f[n][n][p], max(f[n][n][p], f[n][n][p])));
    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值