• [bzoj1084][SCOI2005]最大子矩阵_动态规划_伪·轮廓线dp


    最大子矩阵 bzoj-1084 SCOI-2005

    题目大意:给定一个n*m的矩阵,请你选出k个互不重叠的子矩阵使得它们的权值和最大。

    注释:$1le n le 100$,$1le mle 2$,$1le kle 10$。

    想法:不会。。。看了数据范围..卧槽?m<=2?????我们就可以进行一个简单的轮廓线dp。

    首先,先分m==1和m==2分类讨论,m==1不说了

    m==2

    令f[k][i][j]是第一列到了i,第二列到了j,已经选取了k个矩形的最大权值。

    转移:有3种转移方式:

    1.从左侧转移:f[k][i][j]=max(f[k][i][j] , f[k-1][l][j] + before[1][i] - before[1][l] )。

    2.从右侧转移,转移方程同理。

    3.选取横跨左右的矩阵,此时必须有i==j:f[k][i][j]=max(f[k][i][j] , f[k-1][l][l] + before[1][i] + before[2][i] - before[1][l] - before[2][l])。

    时间复杂度:$O(n^3cdot k)$。

    最后,附上丑陋的代码... ...

    #include<iostream>
    #include<cstdio>
    #define N 110 
    using namespace std;
    int F[12][N],f[12][N][N];
    int n,m,K,s[3][N];
    int a;
    void dispose1()
    {
        for(int k=1;k<=K;k++)
            for(int i=1;i<=n;i++)
            {
                F[k][i]=F[k][i-1];
                for(int j=0;j<=i-1;j++) F[k][i]=max(F[k][i],F[k-1][j]+s[1][i]-s[1][j]);
            }
        int ans=0;
        for(int i=0;i<=K;i++) ans=max(ans,F[i][n]);
        printf("%d
    ",ans);
    }
    void dispose2()
    {
        for(int i=1;i<=n;i++) s[0][i]=s[1][i]+s[2][i];
        for(int k=1;k<=K;k++) for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                f[k][i][j]=max(f[k][i-1][j],f[k][i][j-1]);
                for(int l=0;l<i;l++) f[k][i][j]=max(f[k][i][j],f[k-1][l][j]+s[1][i]-s[1][l]);
                for(int l=0;l<j;l++) f[k][i][j]=max(f[k][i][j],f[k-1][i][l]+s[2][j]-s[2][l]);
                if(i==j)  for(int l=0;l<i;l++) f[k][i][j]=max(f[k][i][j],f[k-1][l][l]+s[0][i]-s[0][l]);
            }
        int ans=0;
        for(int i=0;i<=K;i++) ans=max(ans,f[i][n][n]);
        printf("%d
    ",ans);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&K);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&a);
                s[j][i]=a+s[j][i-1];
            }
        if(m==1) dispose1();
        else dispose2();
        return 0;
    }
    

      小结:一般情况下,我们能求解的只是简单问题的全部版本和复杂问题的特殊版本,所以要对问题抱有敬畏之心(Orz石总)

  • 相关阅读:
    实例模拟struts核心流程
    不同语言下的日期格式化大全
    Android基础之响应Menu键弹出菜单Demo
    c++复习基础要点02 虚函数与模板 与static inline是否共存
    Android listView scroll 恢复滚动位置
    centos本地源搭建——iso
    easy_install和pip区别
    在前台运行Service
    mybatis处理集合、循环、数组和in查询等语句的使用
    java并发库 Lock 公平锁和非公平锁
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9265001.html
Copyright © 2020-2023  润新知