zoukankan      html  css  js  c++  java
  • [SCOI2005]最大子矩阵

    题目描述

    这里有一个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=1和m=2两种情况考虑。

    m=1时,预处理出前缀和sum[]。

    设f[i][j]为到达第i格,已经放了j个子矩阵的最大和,

    那么每次先把f[i][j]的值设为f[i-1][j](第i个元素不属于第j个子矩阵)

    剩下的情况就是第i个元素属于第j个子矩阵了。

    这时候用max(f[p-1][j-1]+(sum[i]-sum[p-1]), 1<=p<=i)更新f[i][j]的最大值,即枚举第j个子矩阵的起始点。

    最终答案为f[n][k]。(边界条件为f[0][j]=0,包含空矩阵)

    m=2时,预处理出分别列的前缀和sum1[],sum2[]。

    设f[i][j][l]为在第1列到达第i格,第2列到达第j格,已经放了l个子矩阵的最大和,

    那么每次先把f[i][j][l]的值设为max(f[i-1][j][l],f[i][j-1][l])(第i行第1列不属于子矩阵或第j行第2列不属于子矩阵,两者取较大值)

    剩下的情况就是第i行第1列和第j行第2列都属于子矩阵了。

    分两种情况:

    一、第i行第1列和第j行第2列属于不同的子矩阵

    分别枚举第i行第1列所在子矩阵的起始点和第j行第2列所在子矩阵的起始点并更新答案,

    即用max(f[p-1][j][l-1]+(sum1[i]-sum1[p-1]), 1<=p<=i)和max(f[i][p-1][l-1]+(sum2[j]-sum2[p-1]),1<=p<=j)更新f[i][j]的最大值。

    二、第i行第1列和第j行第2列属于同一子矩阵

    仅当i==j时才包含这种情况(因为i和j要作为当前状态中子矩阵的末尾)。这时候这个子矩阵的列数必定为2。

    还是一样枚举子矩阵的起始点,

    在i==j的条件下用max(f[p-1][p-1][l-1]+(sum1[i]-sum1[p-1])+(sum2[j]-sum2[p-1]),1<=p<=i)更新答案。

    最后答案为f[n][n][k](边界条件为f[0][0][l]=0,包含空矩阵)

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 using namespace std;
     6 int f1[101][101],f2[101][101][101],a[101][101],sum1[101],sum2[101];
     7 int n,m,k;
     8 int main()
     9 {int i,j,l,p;
    10     cin>>n>>m>>k;
    11     for (i=1;i<=n;i++)
    12     {
    13         for (j=1;j<=m;j++)
    14         {
    15          scanf("%d",&a[i][j]);
    16          if (j==1) sum1[i]=sum1[i-1]+a[i][j];
    17          else sum2[i]=sum2[i-1]+a[i][j];
    18          }
    19     }
    20     if (m==1)
    21     {
    22         for (i=1;i<=n;i++)
    23         for (j=1;j<=k;j++)
    24         {f1[i][j]=f1[i-1][j];
    25             for (l=1;l<=i;l++)
    26              f1[i][j]=max(f1[i][j],f1[l-1][j-1]+sum1[i]-sum1[l-1]);
    27         } 
    28         cout<<f1[n][k];
    29     }
    30     else 
    31     {
    32       for (i=1;i<=n;i++)
    33       {
    34           for (j=1;j<=n;j++)
    35           {
    36                for (l=1;l<=k;l++)
    37                {f2[i][j][l]=max(f2[i-1][j][l],f2[i][j-1][l]);
    38                    for (p=1;p<=i;p++)
    39                     f2[i][j][l]=max(f2[i][j][l],f2[p-1][j][l-1]+sum1[i]-sum1[p-1]);
    40                    for (p=1;p<=j;p++)
    41                     f2[i][j][l]=max(f2[i][j][l],f2[i][p-1][l-1]+sum2[j]-sum2[p-1]); 
    42                    if (i==j)
    43                    for (p=1;p<=i;p++)
    44                     f2[i][j][l]=max(f2[i][j][l],f2[p-1][p-1][l-1]+sum2[j]-sum2[p-1]+sum1[i]-sum1[p-1]); 
    45                }
    46           }
    47       }    
    48       cout<<f2[n][n][k];
    49     }
    50 } 
  • 相关阅读:
    Hive创建表格报Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException的错误
    Hive本地模式安装及遇到的问题和解决方案
    CentOS6 编译安装Mysql5.6.26
    数据结构全攻略--学好数据结构的必经之路
    JAVA项目打开出现红色感叹号!
    前端语言html
    1 利用Anaconda完美解决Python 2与python 3的共存问题
    0 Windows上安装Anaconda和python的教程详解
    回溯算法
    建立结构体
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7326395.html
Copyright © 2011-2022 走看看