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$。

    首先注意到一个性质:$mleq 2$。

    那么我们可以考虑一下,每次一个子矩阵要么只在第一列,要么只在第二列,要么横跨两列。

    那么我们可以设$f[i][j][k]$表示第一列到$i$,第二列到$j$,取了$k$个子矩阵的最大值,转移比较简单,不过注意第三种情况只有$i=j$时才能转移。

    $m=1$时同理,就是把$f[i][j][k]$换成$f[i][k]$就行了。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define inf (1<<30)
     6 
     7 using namespace std;
     8 
     9 int sum[110][2],g[110][2],n,m,k;
    10 
    11 il int gi(){
    12   RG int x=0,q=1; RG char ch=getchar();
    13   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    14   if (ch=='-') q=-1,ch=getchar();
    15   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    16   return q*x;
    17 }
    18 
    19 namespace dp1{
    20   
    21   int f[110][12];
    22   
    23   int main(){
    24     for (RG int i=0;i<=n;++i)
    25       for (RG int j=1;j<=k;++j) f[i][j]=-inf;
    26     for (RG int i=1;i<=n;++i)
    27       for (RG int j=1;j<=k;++j){
    28     f[i][j]=max(f[i][j],f[i-1][j]);
    29     for (RG int p=0;p<i;++p)
    30       f[i][j]=max(f[i][j],f[p][j-1]+sum[i][1]-sum[p][1]);
    31       }
    32     cout<<f[n][k]; return 0;
    33   }
    34   
    35 }
    36 
    37 namespace dp2{
    38   
    39   int f[110][110][12];
    40   
    41   int main(){
    42     for (RG int i=0;i<=n;++i)
    43       for (RG int j=0;j<=n;++j)
    44     for (RG int p=1;p<=k;++p) f[i][j][p]=-inf;
    45     for (RG int i=1;i<=n;++i)
    46       for (RG int j=1;j<=n;++j)
    47     for (RG int p=1;p<=k;++p){
    48       f[i][j][p]=max(f[i][j][p],f[i-1][j][p]);
    49       f[i][j][p]=max(f[i][j][p],f[i][j-1][p]);
    50       for (RG int pre=0;pre<i;++pre)
    51         f[i][j][p]=max(f[i][j][p],f[pre][j][p-1]+sum[i][1]-sum[pre][1]);
    52       for (RG int pre=0;pre<j;++pre)
    53         f[i][j][p]=max(f[i][j][p],f[i][pre][p-1]+sum[j][2]-sum[pre][2]);
    54       if (i==j)
    55         for (RG int pre=0;pre<i;++pre)
    56           f[i][j][p]=max(f[i][j][p],f[pre][pre][p-1]+sum[i][1]-sum[pre][1]+sum[j][2]-sum[pre][2]);
    57     }
    58     cout<<f[n][n][k]; return 0;
    59   }
    60   
    61 }
    62 
    63 int main(){
    64 #ifndef ONLINE_JUDGE
    65   freopen("matrix.in","r",stdin);
    66   freopen("matrix.out","w",stdout);
    67 #endif
    68   n=gi(),m=gi(),k=gi();
    69   for (RG int i=1;i<=n;++i)
    70     for (RG int j=1;j<=m;++j) g[i][j]=gi();
    71   for (RG int i=1;i<=n;++i){
    72     sum[i][1]=sum[i-1][1]+g[i][1];
    73     sum[i][2]=sum[i-1][2]+g[i][2];
    74   }
    75   if (m==1) dp1::main();
    76   if (m==2) dp2::main();
    77   return 0;
    78 }
  • 相关阅读:
    ssm框架配置文件
    接口调用post请求参数在body中
    mysql三种连接方式
    jwt认证登录
    JWT工具类
    token的创建及解析
    IIS目录
    C# 增加多个分部类
    计算机知识
    Kibana 的安装(Windows版本)
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7663362.html
Copyright © 2011-2022 走看看