zoukankan      html  css  js  c++  java
  • 洛谷P2331 [SCOI2005] 最大子矩阵[序列DP]

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    3 2 2
    1 -3
    2 3
    -2 3
    
    输出样例#1:
    9

    m分类讨论
    m=1,f[i][j]表示前i个选了j个矩阵 复杂度O(n*n*k)
    m=2,f[i][j][k]表示第一行前i个第二行前j个选了k个矩阵,转移注意i==j可以上下都选
    数据弱,随便一个全负的矩阵就把没初始化的卡住了
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const int N=105,INF=1e9+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m,K,a[N][3],d[N][15],s[N][3],ans=-INF;
    void dp1(){
        for(int i=1;i<=n;i++)
            s[i][1]=s[i-1][1]+a[i][1];
        for(int j=1;j<=K;j++) d[0][j]=-INF;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=K;j++){
                d[i][j]=d[i-1][j];
                for(int z=0;z<i;z++) d[i][j]=max(d[i][j],d[z][j-1]+s[i][1]-s[z][1]);
            }
    }
    int f[N][N][15];
    void dp2(){
        for(int i=1;i<=n;i++){
            s[i][1]=s[i-1][1]+a[i][1]; //printf("s1 %d %d 
    ",i,s[i][1]);
            s[i][2]=s[i-1][2]+a[i][2];    //printf("s2 %d %d 
    ",i,s[i][2]);
        }
        for(int i=1;i<=max(n,m);i++) for(int j=1;j<=K;j++) f[i][0][j]=f[0][i][j]=-INF;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=K;k++){
                    f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);
                    for(int z=0;z<i;z++) f[i][j][k]=max(f[i][j][k],f[z][j][k-1]+s[i][1]-s[z][1]);
                    for(int z=0;z<j;z++) f[i][j][k]=max(f[i][j][k],f[i][z][k-1]+s[j][2]-s[z][2]);
                    if(i==j) for(int z=0;z<i;z++)
                        f[i][j][k]=max(f[i][j][k],f[z][z][k-1]+s[i][1]-s[z][1]+s[i][2]-s[z][2]);
                    //printf("f %d %d %d %d
    ",i,j,k,f[i][j][k]);
                }
    }
    int main(int argc, const char * argv[]) {
        n=read();m=read();K=read();
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read();
        if(m==1) {dp1();printf("%d",d[n][K]);}
        else {dp2();printf("%d",f[n][n][K]);}
        //printf("
    
    %d",a[1][2]);
        return 0;
    }
     
  • 相关阅读:
    Overloaded的方法是否可以改变返回值的类型
    parseXXX的用法
    java的类型转换问题。int a = 123456;short b = (short)a;System.out.println(b);为什么结果是-7616?
    UVA 10405 Longest Common Subsequence(简单DP)
    POJ 1001 Exponentiation(大数处理)
    POJ 2318 TOYS(计算几何)(二分)
    POJ 1265 Area (计算几何)(Pick定理)
    POJ 3371 Flesch Reading Ease (模拟题)
    POJ 3687 Labeling Balls(拓扑序列)
    POJ 1094 Sorting It All Out(拓扑序列)
  • 原文地址:https://www.cnblogs.com/candy99/p/5935091.html
Copyright © 2011-2022 走看看