• 【BZOJ 1084】 1084: [SCOI2005]最大子矩阵 (DP)


    1084: [SCOI2005]最大子矩阵

    Description

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

    Input

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

    Output

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

    Sample Input

    3 2 2
    1 -3
    2 3
    -2 3

    Sample Output

    9

    HINT

    【分析】

      终于考完ws的期末考回来刷题了,表示很桑心先刷一道水题淡定一下。。。

      表示又是智障看错了以为k是100。

      思路很简单,m<=2,分m=1 m=2两种情况讨论。

      m=1:

      f[i][j]表示选了前i个数,j个矩阵的最优值,枚举最后一个矩阵转移。

      m=2:

      f[i][j][k]表示第一行选了前i个数,第二行选了前j个数,一共k个矩阵的最优值。

      状态:1、枚举第一行最后一个矩阵。

         2、枚举第二行最后一个矩阵。

         3、当i=j,可以两行一起选,枚举两行一起选的最后一个矩阵。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define Maxn 110
     8 
     9 int a[2][Maxn],h[2][Maxn],f[Maxn][Maxn];
    10 int d[Maxn][Maxn][Maxn];
    11 
    12 int mymax(int x,int y) {return x>y?x:y;}
    13 
    14 int main()
    15 {
    16     int n,m,k;
    17     scanf("%d%d%d",&n,&m,&k);
    18     for(int i=1;i<=n;i++)
    19      for(int j=0;j<m;j++) scanf("%d",&a[j][i]);
    20     h[0][0]=h[1][0]=0;
    21     for(int i=0;i<m;i++)
    22      for(int j=1;j<=n;j++) h[i][j]=h[i][j-1]+a[i][j];
    23     int ans=0;
    24     if(m==1)
    25     {
    26         memset(f,0,sizeof(f));
    27         for(int i=1;i<=n;i++)
    28          for(int j=1;j<=i&&j<=k;j++)
    29          {
    30              for(int l=0;l<i;l++)
    31                 f[i][j]=mymax(f[i][j],f[l][j-1]+h[0][i]-h[0][l]);
    32             f[i][j]=mymax(f[i][j],f[i-1][j]);
    33          }
    34         for(int i=k;i<=n;i++) ans=mymax(ans,f[i][k]);
    35     }
    36     else
    37     {
    38         memset(d,0,sizeof(d));
    39         for(int i=0;i<=n;i++)
    40          for(int j=0;j<=n;j++)
    41           for(int l=1;l<=k;l++)
    42           {
    43               for(int p=0;p<i;p++) d[i][j][l]=mymax(d[i][j][l],d[p][j][l-1]+h[0][i]-h[0][p]);
    44               for(int p=0;p<j;p++) d[i][j][l]=mymax(d[i][j][l],d[i][p][l-1]+h[1][j]-h[1][p]);
    45               if(i==j)
    46               {
    47                   for(int p=0;p<i;p++) d[i][j][l]=mymax(d[i][j][l],d[p][p][l-1]+h[0][i]+h[1][j]-h[0][p]-h[1][p]);
    48               }
    49               d[i][j][l]=mymax(d[i][j][l],d[i-1][j][l]);
    50               d[i][j][l]=mymax(d[i][j][l],d[i][j-1][l]);
    51               if(l==k) ans=mymax(ans,d[i][j][l]);
    52               // printf("d[%d][%d][%d]= %d
    ",i,j,l,d[i][j][l]);
    53           }
    54     }
    55     printf("%d
    ",ans);
    56     return 0;
    57 }
    View Code

    2017-01-11 09:11:39

  • 相关阅读:
    Nop中的Cache浅析
    使用DapperExtensions实现简单仓储
    使用nodejs爬取拉勾苏州和上海的.NET职位信息
    使用Microsoft Fakes进行单元测试(2)
    使用Microsoft Fakes进行单元测试(1)
    小程序之滚动到页面底部
    小程序之动态修改页面标题
    小程序之面试题
    小程序之公共组件的开发
    小程序之web-view打开外部链接
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6272323.html
Copyright © 2020-2023  润新知