【bzoj1084】最大子矩阵

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
 
Solution
我们发现,这个矩阵惊人的只有两行
一行的话,应当是很显然的
f[i][j]代表1~i取了j段,暴力转移即可
两行的话
f[i][j][k]第一行前i个,第二行前j个,共取了k段
暴力枚举这一段有多长即可
 
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#include<vector>
#include<set>
#define il inline
#define re register
#define inf 1000000000
using namespace std;
int n,m,a[101],b[101],p,g[101][101],f[101][101][101];
int main(){
    scanf("%d%d%d",&n,&m,&p);
    if(m==1){
        for(int i=1,x;i<=n;i++){
            scanf("%d",&x);
            a[i]=a[i-1]+x;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=p;j++){
                g[i][j]=g[i-1][j];
                for(int k=0;k<i;k++)
                    g[i][j]=max(g[i][j],g[k][j-1]+a[i]-a[k]);
            }
        }
        cout<<g[n][p];return 0;
    }
    for(int i=1,x,y;i<=n;i++){
        scanf("%d%d",&x,&y);
        a[i]=a[i-1]+x;
        b[i]=b[i-1]+y;
    }
    for(int k=1;k<=p;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);
                for(int l=0;l<i;l++) f[i][j][k]=max(f[l][j][k-1]+a[i]-a[l],f[i][j][k]);
                for(int l=0;l<j;l++) f[i][j][k]=max(f[i][l][k-1]+b[j]-b[l],f[i][j][k]);
                if(i==j){
                    for(int l=0;l<i;l++)
                        f[i][j][k]=max(f[i][j][k],f[l][l][k-1]+a[i]-a[l]+b[j]-b[l]);    
                }
            }
    cout<<f[n][n][p]<<endl;
    return 0;
}

 

posted @ 2016-11-20 22:30  ExiledPoet  阅读(92)  评论(0编辑  收藏