• BZOJ1084: [SCOI2005]最大子矩阵


    【传送门:BZOJ1084


    简要题意:

      给出n行m列的矩阵,要求选出k个不互相覆盖子矩阵,使得选出的k个子矩阵的和最大,求出和


    题解:

      DP

      我的DP方程可能有些麻烦。。

      首先面向数据编程,因为m<=2,所以先把m=1的情况求出来,这个就不用讲了

      然后对于m=2的情况,我们设:

      f[i][k][0]为第i行不选左也不选右,且共有k个子矩阵的最大和

      f[i][k][1]为第i行只选择左边成为子矩阵且共有k个子矩阵的最大和

      f[i][k][2]为第i行只选择右边成为子矩阵且共有k个子矩阵的最大和

      f[i][k][3]为第i行左右边都成为子矩阵,但是并不在同一个子矩阵,且共有k个子矩阵的最大和

      f[i][k][4]为第i行左右边都成为子矩阵,而且在同一个子矩阵,且共有k个子矩阵的最大和

      状态转移不想写了,太烦了。。自行yy吧


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int f1[110],f2[110],a[110],b[110];
    int f[110][11][5];
    int s1[110][110],s2[110][110];
    int s[110][110];
    int main()
    {
        int n,m,K;
        scanf("%d%d%d",&n,&m,&K);
        int ans=0;
        if(m==1)
        {
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
            {
                for(int j=i;j<=n;j++)
                {
                    int d=0;
                    for(int k=j;k>=i;k--)
                    {
                        d+=a[k];
                        s[i][j]=max(s[i][j],d);
                    }
                }
            }
            memset(f,0,sizeof(f));
            for(int k=1;k<=K;k++)
            {
                for(int i=1;i<=n;i++)
                {
                    for(int j=0;j<i;j++)
                    {
                        f[i][k][0]=max(f[i][k][0],f[j][k-1][0]+s[j+1][i]);
                        ans=max(ans,f[i][k][0]);
                    }
                }
            }
        }
        else
        {
            memset(f,-63,sizeof(f));
            for(int i=0;i<=n;i++) for(int k=0;k<=K;k++) f[i][k][0]=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",&a[i],&b[i]);
                for(int k=1;k<=K;k++)
                {
                    //不取
                    f[i][k][0]=max(f[i-1][k][0],max(f[i-1][k][1],max(f[i-1][k][2],max(f[i-1][k][3],f[i-1][k][4]))));
                    //只取左
                    f[i][k][1]=max(max(f[i-1][k][1],f[i-1][k][3]),max(f[i-1][k-1][0],max(f[i-1][k-1][2],f[i-1][k-1][4])))+a[i];
                    //只取右
                    f[i][k][2]=max(max(f[i-1][k][2],f[i-1][k][3]),max(f[i-1][k-1][0],max(f[i-1][k-1][1],f[i-1][k-1][4])))+b[i];
                    //左右都取,但左右两边都不在一个子矩阵内
                    f[i][k][3]=max(f[i-1][k][3],max(f[i-1][k-1][1],f[i-1][k-1][2]))+a[i]+b[i];
                    if(k>=2) f[i][k][3]=max(f[i][k][3],max(f[i-1][k-2][0],f[i-1][k-2][4])+a[i]+b[i]);
                    //左右都取,但左右两边都在一个子矩阵内
                    f[i][k][4]=max(f[i-1][k-1][0],max(f[i-1][k-1][1],max(f[i-1][k-1][2],max(f[i-1][k-1][3],f[i-1][k][4]))))+a[i]+b[i];
                    ans=max(ans,max(f[i][k][0],max(f[i][k][1],max(f[i][k][2],max(f[i][k][3],f[i][k][4])))));
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    android四大组件之contentprovider
    android自定义控件及自定义组合控件
    android四大组件之activity
    监听鼠标滚动事件,如滚动鼠标出现返回顶部按钮
    滚动鼠标出现某一元素
    checked 选择框选中
    原生JS一些操作
    闭合浮动的方法css
    合理提升WEB前端性能
    JS数组操作
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8760714.html
Copyright © 2020-2023  润新知