bzoj1084: [SCOI2005]最大子矩阵

Description

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

Input

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

Output

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

Sample Input

3 2 2
1 -3
2 3
-2 3

Sample Output

9

一维的方程很简单f[i][j]=max(f[k][j-1]+sum[i]-sum[k]);k<i

二维的需要考虑组成的并不是一个矩形的情况 令f[i][j][k]为第一行进行到i 第二行进行到j 分了k段的最大值

则有f[i][j][k]=max(f[l][j][k-1]+sum[1][i]-sum[1][l],f[j][l][k-1]+sum[2][j]-sum[2][l])

如果i==j那么还可以从f[l][l][k-1]+sum[1][i]-sum[1][l]+sum[2][j]-sum[2][l]转移过来

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int sum[110][3];
int f[110][20];
int A[110][3];
int g[110][110][20];
int main(){
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    int n,m,k;
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&A[i][j]);
    //for(int i=1;i<=n;i++)
    //  printf("%d %d\n",A[i][1],A[i][2]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            sum[i][j]=sum[i-1][j]+A[i][j];
    if(m==1){
        for(int i=1;i<=n;i++){
            for(int l=1;l<=k;l++){
                for(int j=1;j<=i;j++)
                    f[i][l]=max(f[i][l],f[j-1][l-1]+sum[i][1]-sum[j-1][1]);
                f[i][l]=max(f[i][l],f[i-1][l]);
            }
        }
        printf("%d\n",f[n][k]);
    }
    else {
        for(int l=1;l<=k;l++)
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    g[i][j][l]=max(g[i][j-1][l],g[i-1][j][l]);
                    for(int d=0;d<i;d++)
                        g[i][j][l]=max(g[i][j][l],g[d][j][l-1]+sum[i][1]-sum[d][1]);
                    for(int d=0;d<j;d++)
                        g[i][j][l]=max(g[i][j][l],g[i][d][l-1]+sum[j][2]-sum[d][2]);
                    if(i==j)
                        for(int d=0;d<i;d++)
                            g[i][j][l]=max(g[i][j][l],g[d][d][l-1]+sum[i][1]-sum[d][1]+sum[j][2]-sum[d][2]);
                }
            }
        printf("%d\n",g[n][n][k]);
    }
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值