zoukankan      html  css  js  c++  java
  • BZOJ1084 [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
     
     
    正解:DP
    解题报告:
      乍一看,感觉像是才做过的那道最大子矩阵和,只不过那道题是固定了三块而这道题是k块,瞬间各种傻眼。
      结果突然发现,m<=2。。。显然可以当做特殊性质。
      f[i][j][k]表示第一列处理到第i个,第二列处理到第j个并且选取了k个子矩阵的最优值。转移的话要不从左边选择一块,要不从右边选择一块,又或者两列都占的矩形,但是只有i、j相等才可能两列都占,否则无法刚好到达i。
      代码如下:
     
     
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 using namespace std;
     8 const int MAXN = 150;
     9 int n,m,k;
    10 int dp[MAXN][11],f[MAXN][MAXN][11];
    11 int a[2][MAXN];
    12 int sum[2][MAXN];
    13 
    14 inline int getint(){
    15     int w=0,q=1;char c=getchar();
    16     while(c!='-' && (c<'0' || c>'9')) c=getchar();
    17     if(c=='-') q=-1,c=getchar();
    18     while(c>='0' && c<='9') w=w*10+c-'0',c=getchar();
    19     return w*q;
    20 }
    21 
    22 int main()
    23 {
    24     n=getint(); m=getint(); k=getint();
    25     if(m==1) {//特判只有一列的情况
    26     for(int i=1;i<=n;i++) a[0][i]=getint(),sum[0][i]=sum[0][i-1]+a[0][i];
    27 
    28     for(int i=1;i<=n;i++)
    29         for(int l=1;l<=k;l++) { 
    30         dp[i][l]=dp[i-1][l];
    31         for(int j=0;j<i;j++)
    32             dp[i][l]=max(dp[j][l-1]+sum[0][i]-sum[0][j],dp[i][l]);
    33         }
    34     printf("%d",dp[n][k]);
    35 
    36     } else{
    37     for(int i=1;i<=n;i++) a[0][i]=getint(),sum[0][i]=sum[0][i-1]+a[0][i],a[1][i]=getint(),sum[1][i]=sum[1][i-1]+a[1][i];
    38 
    39     for(int l=1;l<=k;l++)
    40         for(int i=1;i<=n;i++)
    41         for(int j=1;j<=n;j++) {
    42             f[i][j][l]=max(f[i-1][j][l],f[i][j-1][l]);
    43             for(int from=0;from<i;from++) f[i][j][l]=max(f[i][j][l],f[from][j][l-1]+sum[0][i]-sum[0][from]);//枚举从左边转移
    44             for(int from=0;from<j;from++) f[i][j][l]=max(f[i][j][l],f[i][from][l-1]+sum[1][j]-sum[1][from]);//枚举从右边转移
    45             if(i==j)
    46             for(int from=0;from<i;from++)//枚举从两边转移
    47                 f[i][j][l]=max(f[i][j][l],f[from][from][l-1]+sum[0][i]-sum[0][from]+sum[1][j]-sum[1][from]);
    48         }
    49     printf("%d",f[n][n][k]);
    50     }
    51 
    52     return 0;
    53 }
  • 相关阅读:
    8.SpringMVC参数传递
    9.SpringMVC和json结合传递参数
    20160815命令行进入其他盘
    5.SpringMVC静态文件的访问
    6.SpringMVC注解启用
    7.SpringMVC注解优化
    3.SpringMVC修改配置文件路径和给界面传递数据
    rails
    SVN Merge合并 Patch打补丁
    Windows环境下怎么在文件夹下打开cmd命令行
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5793708.html
Copyright © 2011-2022 走看看