1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2333 Solved: 1148
[Submit][Status][Discuss]
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

解答:分情况
m=1时,f1[k][i]表示1~i内含有k个子矩阵的状态
m=2时,f[k][i][j]表示第一列1~i,第二列1~j含有k个子矩阵的状态
两种情况的状态转移见代码理解。

#include<cstdio>
#include<cstring>
using namespace std;
int a[110][3],n,m,K,f1[11][110],f[11][110][110],s[110],s1[110],s2[110];
int mymax(int x,int y){ return x>y?x:y;}
int main()
{
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
    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]);
    if(m==1)
    {
        s[0]=0;
        for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i][1];
        memset(f1,0,sizeof(f1));

        for(int k=1;k<=K;k++)
        {
            f1[k][k]=s[k];
            for(int i=k+1;i<=n;i++)
            {
                f1[k][i]=f1[k][i-1];
                for(int j=k;j<=i;j++)
                    f1[k][i]=mymax(f1[k][i],f1[k-1][j-1]+s[i]-s[j-1]);
            }
        }
        printf("%d\n",f1[K][n]);
    }
    else //if m==2
    {
        s1[0]=s2[0]=0;
        for(int i=1;i<=n;i++) s1[i]=s1[i-1]+a[i][1],s2[i]=s2[i-1]+a[i][2];
        memset(f,0,sizeof(f));
        for(int k=1;k<=K;k++)
        {

            for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                f[k][i][j]=mymax(f[k][i-1][j],f[k][i][j-1]);
                for(int l=1;l<=i;l++)f[k][i][j]=mymax(f[k][i][j],f[k-1][l-1][j]+s1[i]-s1[l-1]);
                for(int l=1;l<=j;l++)f[k][i][j]=mymax(f[k][i][j],f[k-1][i][l-1]+s2[j]-s2[l-1]);
                if(i==j)for(int l=1;l<=j;l++)f[k][i][j]=mymax(f[k][i][j],f[k-1][l-1][l-1]+s1[i]-s1[l-1]+s2[j]-s2[l-1]);
            }
        }
        printf("%d\n",f[K][n][n]);

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值