bzoj1084: [SCOI2005]最大子矩阵(dp)

1084: [SCOI2005]最大子矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2865  Solved: 1428
[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、2两种情况,所以分开讨论。
m=1 这部分还是比较水的,f[i][j]表示前i行选j个矩形的最大分值。
方程f[i][j]=max(f[i-1][j],max{f[k][j-1]+sum[i]-sum[k]|0<=k<=i})(sum是前缀和)
* m=2
f[i][j][k]表示第一列前i行,第二列前j行选k个矩形的最大分值,方程和m=1是较相似,但多了i=j时的情况,
叙述比较麻烦,具体看代码。
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 105

using namespace std;
int dp[N][N][N],f[N][N],s[N][2],sum[N],a[N],b[N];
int n,m,k,ans;

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    if(m==1)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        for(int i=1;i<=n;i++)
        {
            f[i][0]=0;
            for(int j=1;j<=k;j++)
            {
                f[i][j]=f[i-1][j];
                for(int l=1;l<=i;l++)
                  f[i][j]=max(f[i][j],f[l][j-1]+sum[i]-sum[l]);
            }
        }
        printf("%d\n",f[n][k]);
    }    
    
    else
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            s[i][0]=s[i-1][0]+a[i];
            s[i][1]=s[i-1][1]+b[i];
        }
        for(int i1=1;i1<=n;i1++) for(int i2=1;i2<=n;i2++)
        {
            dp[i1][i2][0]=0;
            for(int j=1;j<=k;j++)
            {
                dp[i1][i2][j]=max(dp[i1-1][i2][j],dp[i1][i2-1][j]);
                for(int l=0;l<i1;l++)
                  dp[i1][i2][j]=max(dp[i1][i2][j],dp[l][i2][j-1]+s[i1][0]-s[l][0]);
                for(int l=0;l<i2;l++)
                  dp[i1][i2][j]=max(dp[i1][i2][j],dp[i1][l][j-1]+s[i2][1]-s[l][1]);
                if(i1==i2)
                {
                    for(int l=0;l<i1;l++)
                      dp[i1][i2][j]=max(dp[i1][i2][j],dp[l][l][j-1]+s[i1][0]-s[l][0]+s[i2][1]-s[l][1]);
                }
            }
        }
        printf("%d\n",dp[n][n][k]);
    }
    return 0;
}

 

posted @ 2017-08-13 21:06  安月冷  阅读(144)  评论(0编辑  收藏  举报