[SCOI2005][BZOJ 1084]最大子矩阵

Description

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

Input

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

Output

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

题解:

  看了半天,突然发现,m小于等于2啊。

  然后就乱dp一波,除了转移写起来很麻之外,就没什么了。

  令f[i][j][k]表示当前第i行,以选中j个矩阵,当前行的取法为k的得分数,(取法只有5种啦)。

代码:

#include<bits/stdc++.h>
using namespace std;
inline 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<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
    return x*f;
}
#define MN 105
#define inf 0x7f
int n,m,k,a[MN][3],ans;
int f[MN][15][6];
void rw(int &x,int y){if(y>x)x=y;}
int main(){
    n=read(),m=read(),k=read();
    register int i,j;
    for(i=1;i<=n;i++)for(j=1;j<=m;j++) a[i][j]=read();
    if(m==1){
        for(i=1;i<=n;i++) for(j=1;j<=k;j++){
            rw(f[i][j][0],f[i-1][j][0]);
            rw(f[i][j][0],f[i-1][j][1]);
            rw(f[i][j][1],f[i-1][j][1]+a[i][1]);
            rw(f[i][j][1],f[i-1][j-1][0]+a[i][1]);
        }
        printf("%d\n",max(f[n][k][1],f[n][k][0]));
    }
    else{
        memset(f,-inf,sizeof f);
        for(i=0;i<=n;i++)for(j=0;j<=k;j++) f[i][j][1]=0;
        for(i=1;i<=n;i++)for(j=1;j<=k;j++){
            for(int h=1;h<=5;h++) rw(f[i][j][1],f[i-1][j][h]);

            f[i][j][2]=max(f[i-1][j][2],f[i-1][j][5])+a[i][1];
            f[i][j][3]=max(f[i-1][j][3],f[i-1][j][5])+a[i][2];
            rw(f[i][j][2],f[i-1][j-1][4]+a[i][1]);
            rw(f[i][j][3],f[i-1][j-1][4]+a[i][2]);
            rw(f[i][j][2],max(f[i-1][j-1][1],f[i-1][j-1][3])+a[i][1]);
            rw(f[i][j][3],max(f[i-1][j-1][1],f[i-1][j-1][2])+a[i][2]);

            f[i][j][4]=max(f[i-1][j-1][1],f[i-1][j][4])+a[i][1]+a[i][2];
            rw(f[i][j][4],max(f[i-1][j-1][2],f[i-1][j-1][3])+a[i][1]+a[i][2]);
            rw(f[i][j][4],f[i-1][j-1][5]+a[i][1]+a[i][2]);

            f[i][j][5]=f[i-1][j][5]+a[i][1]+a[i][2];
            rw(f[i][j][5],max(f[i-1][j-1][2],f[i-1][j-1][3])+a[i][1]+a[i][2]);
            if(j>=2) rw(f[i][j][5],max(f[i-1][j-2][1],f[i-1][j-2][4])+a[i][1]+a[i][2]);
        }
        ans=-1e12;
        for(i=1;i<=5;i++) rw(ans,f[n][k][i]);
        printf("%d\n",ans);
    }
    return 0;
}


来自PaperCloud的博客,未经允许,请勿转载,TKS!

原文地址:https://www.cnblogs.com/PaperCloud/p/9040483.html

时间: 2024-10-30 03:28:07

[SCOI2005][BZOJ 1084]最大子矩阵的相关文章

BZOJ 1084 最大子矩阵 终于过了

一开始看到这道题,由于觉得m <= 2, 所以觉得这是道水题,回去后想了一下.在晚上来机房的时候已经想出来了,但是我必须承认细节决定成败.远在一个小时前我就已经把算法的主体都写好了,但是就是一直WA,为什么就是各种粗心,真心想捏死自己.一个小时就这么白白浪费了.我希望明天的我能变得强大一点.在有了今日惨痛的教训之后. 这道题并不难.用d[i][j][k] 来表示状态.i表示第几行,j表示之前取了多少个矩阵,k表示上一行的状态.即上一行的矩阵取法.如果k == 0 那么没有一个矩阵延伸到上一行,如

BZOJ 1084 最大子矩阵

http://www.lydsy.com/JudgeOnline/problem.php?id=1084 思路:分m=1和m=2操作 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int f[1005][1005],F[1005][1005][11]; 7 int sum[10005],su

[BZOJ 1084][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 HINT Source 刚开始没看清题,以

【SCOI2005】 最大子矩阵 BZOJ 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 思路 看到题目:好难啊..一点思路都没有.

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

题目链接:BZOJ - 1084 题目分析 我看的是神犇BLADEVIL的题解. 1)对于 m = 1 的情况, 首先可能不取 Map[i][1],先 f[i][k] = f[i - 1][k];  再考虑取一段新的的情况,用 max(f[j][k - 1] + Sum[i][1] - Sum[j][1])   (0 <= j < i)  更新 f[i][j]: 2) 对于 m = 2 的情况,用 f[i][j][k] 表示左列取到第 i 个,右列取到第 j 个,共 k 个矩形的最优值. 首先

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

最多只有2列..分开来dp 1列 dp(x, k) = max( dp(x - 1, k), dp(p, k - 1) + sum(p+1~x) ) 2列 dp(a, b, k) = max( dp(a - 1, b, k), dp(a, b - 1, k), dp(p, b, k - 1) + sum1(p+1~a), dp(a, p, k - 1) + sum2(p+1~b) ) 当a = b, dp(a, b, k)还可以用dp(p, p, k - 1) + SUM(p+1~a) (0 ≤

bzoj 1084;vijos 1191 [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 直接拎dp #include<cstdio

BZOJ 1084 SCOI2005 最大子矩阵 动态规划

题目大意:给出一个矩阵,求在这个矩阵中取出k个不重叠的矩阵的最大和. 思路:怎么做? 这个问题困扰我好几天的时间,终于再一次读题: ... .. ... 2??!! 这尼玛逗我??直接说最多两列不好么?还用矩阵吓唬我? 好吧下次我一定认真看题.. 我的做法比较渣,算出来的时间复杂度是O(m^3*k),但是只有最多3000w,还是可以过的. 状态:f[i][j][k]表示第一列到了第i个格子,第二列到了第j个格子,已经选取了k个矩阵的最大得数. 转移:先把现有的状态向后转移,转移成f[i'][j'

bzoj 1084

看到m<=2,果断乱搞..然后搞着搞着自己被搞晕了233333 1 #include<bits/stdc++.h> 2 #define inc(i,l,r) for(i=l;i<=r;i++) 3 #define dec(i,l,r) for(i=l;i>=r;i--) 4 #define inf 1e9 5 #define ll long long 6 #define mem(a) memset(a,0,sizeof(a)) 7 using namespace std; 8