【BZOJ 1084】 [SCOI2005]最大子矩阵(DP)

题链

http://www.lydsy.com/JudgeOnline/problem.php?id=1084

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<=2,那么可以分类讨论:
(1)当m1时,设d1 [ i ] [k]为从考虑前i行找到k个子矩阵,转移方程为
$ d1[i][k] = max ( d1[i][k] , d1[j][k-1] + sum[i] - sum[j] ) $
(2)当m
2时,设d2 [ i ] [ j ] [ k ] 从考虑第一列前i行,第二列前j行找到k个子矩阵,转移方程为
$ d2[i][j][k]=max(d2[i][j][k],d2[x][j][k-1]+s1[i]-s1[x]);$
$ d2[i][j][k]=max(d2[i][j][k],d2[i][x][k-1]+s2[j]-s2[x]);$
$ d2[i][j][k]=max(d2[i][j][k],d2[x][x][k-1]+s1[i]-s1[x]+s2[j]-s2[x]);$

参考代码

#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1000000000
#define mod 1000000007
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void Out(ll a) {
    if(a<0) putchar('-'),a=-a;
    if(a>=10) Out(a/10);
    putchar(a%10+'0');
}
const int N=105;
int d1[N][15],d2[N][N][15];
int sum[N];
int s1[N],s2[N];
int main(){
    int n=read(),m=read(),K=read();
    if(m==1){
        for(int i=1;i<=n;i++){
            int x=read();
            sum[i]=sum[i-1]+x;
        }
        for(int i=1;i<=n;i++) for(int k=1;k<=K;k++){
           d1[i][k]=d1[i-1][k];
           for(int j=i-1;j>=0;j--)
           d1[i][k]=max(d1[i][k],d1[j][k-1]+sum[i]-sum[j]);
        }
        Out(d1[n][K]);
    }
    else{
        for(int i=1;i<=n;i++){
            int x=read(),y=read();
            s1[i]=s1[i-1]+x;
            s2[i]=s2[i-1]+y;
        }
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=K;k++){
            d2[i][j][k]=max(d2[i-1][j][k],d2[i][j-1][k]);
            for(int x=0;x<i;x++)  d2[i][j][k]=max(d2[i][j][k],d2[x][j][k-1]+s1[i]-s1[x]);
            for(int x=0;x<j;x++)  d2[i][j][k]=max(d2[i][j][k],d2[i][x][k-1]+s2[j]-s2[x]);
            if(i==j) for(int x=0;x<i;x++)
            d2[i][j][k]=max(d2[i][j][k],d2[x][x][k-1]+s1[i]-s1[x]+s2[j]-s2[x]);
        }
        Out(d2[n][n][K]);
    }
    return 0;
}

posted @ 2017-07-11 22:20  江南何采莲  阅读(58)  评论(0编辑  收藏