• 【SCOI 2005】 最大子矩阵


    【题目链接】

               点击打开链接

    【算法】

              动态规划

              我们发现,M只有两种取值,1和2,那么,只需分类讨论即可

              当M = 1时,其实这个问题就成了就最大连续子段和的问题,只不过要选K段而已

              用f[i][j]表示选到第i行,选了j段,那么,显然有 : f[i][j] = max{f[i-1][j],f[k][j-1] + sum[i] - sum[k]}(sum为前缀和)

              当M = 2时,我们用f[i][j][k]表示第一列选到第i行,第二列选到第j行,选了k段

              那么 :

                      如果不取,f[i][j][k] = max{f[i-1][j][k],f[i][j-1][k]}

                      如果第一列取,f[i][j][k] = max{f[t][j][k-1] + sum[i][1] - sum[t][1]}

                      如果第二列取,   f[i][j][k] = max{f[i][t][k-1] + sum[i][2] - sum[t][2]}

                      如果第一二列都取,我们可以把它看成两种情况

                      第一种,看成一个大矩形,f[i][j][k] = max{f[t][t][k-1] + sum[i][1] - sum[t][1] + sum[i][2] - sum[t][2]}

                      第二种,看成两个小矩形,f[i][j][k] = max{f[t][t][k-2] + sum[i][1] - sum[t][1] + sum[i][2] - sum[t][2]} (k > 1)

              此题就是需要我们认真读题,如果发现了"1<=M<=2",那么,问题就变得简单多了!

    【代码】

                

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 110
    #define MAXK 12
    const int INF = 2e9;
    
    int n,m,k;
    
    inline void solve1()
    {
            int i,j,t;
            static int a[MAXN],sum[MAXN],f[MAXN][MAXK];
            for (i = 0; i <= n; i++)
            {
                    for (j = 1; j <= k; j++)
                    {
                            f[i][j] = -INF;
                    }
            }
            memset(sum,0,sizeof(sum));
            for (i = 1; i <= n; i++)
            {
                    scanf("%d",&a[i]);
                    sum[i] = sum[i-1] + a[i];
            }
            for (i = 1; i <= n; i++)
            {
                    for (j = 1; j <= k; j++)
                    {
                            f[i][j] = f[i-1][j];
                            for (t = 0; t < i; t++)
                            {
                                    f[i][j] = max(f[i][j],f[t][j-1]+sum[i]-sum[t]);
                            }
                    }
            }
            printf("%d
    ",f[n][k]);
    }
    inline void solve2()
    {
            int i,j,x,y;
            static int a[MAXN][3],sum[MAXN][3],f[MAXN][MAXN][MAXK];
            for (i = 0; i <= n; i++)
            {
                    for (j = 0; j <= n; j++)
                    {
                            for (x = 1; x <= k; x++)
                            {
                                    f[i][j][x] = -INF;
                            }
                    }
            }
            memset(sum,0,sizeof(sum));
            for (i = 1; i <= n; i++)
            {
                    scanf("%d%d",&a[i][1],&a[i][2]);
                    sum[i][1] = sum[i-1][1] + a[i][1];
                    sum[i][2] = sum[i-1][2] + a[i][2];
            }
            for (i = 1; i <= n; i++)
            {
                    for (j = 1; j <= n; j++)
                    {
                            for (x = 1; x <= k; x++)
                            {
                                    f[i][j][x] = max(f[i-1][j][x],f[i][j-1][x]);
                                    for (y = 0; y < i; y++) f[i][j][x] = max(f[i][j][x],f[y][j][x-1]+sum[i][1]-sum[y][1]);
                                    for (y = 0; y < j; y++) f[i][j][x] = max(f[i][j][x],f[i][y][x-1]+sum[j][2]-sum[y][2]);
                                    if (i == j)
                                    {
                                            for (y = 0; y < i; y++)
                                            {
                                                    f[i][j][x] = max(f[i][j][x],f[y][y][x-1]+sum[i][1]-sum[y][1]+sum[i][2]-sum[y][2]);
                                                    if (x > 1) f[i][j][x] = max(f[i][j][x],f[y][y][x-2]+sum[i][1]-sum[y][1]+sum[i][2]-sum[y][2]);
                                            }
                                    }
                            }
                    }
            }
            printf("%d
    ",f[n][n][k]);
    }
    
    int main()
    {
        
            scanf("%d%d%d",&n,&m,&k);
            if (m == 1) solve1();
            else solve2();
            
            return 0;
    }
  • 相关阅读:
    C# 把带有父子关系的数据转化为------树形结构的数据 ,以及 找出父子级关系的数据中里面的根数据Id
    基于角色的菜单按钮权限的设计及实现
    基于记忆性的中值滤波O(r)与O(1)复杂度的算法实现
    Canny算法检测边缘
    图像平滑去噪之高斯滤波器
    运动元素提取,基于帧间差分与背景差分
    基于RGB与HSI颜色模型的图像提取法
    基于阈值的灰度图像提取法
    C语言深入学习
    大津法实现图像二值化
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196344.html
Copyright © 2020-2023  润新知