• luogu 2331 [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

    分析

    方法1

    O(n3*k):luogu 2331 题解

    这题中,空矩阵也算子矩阵

    m == 1时dp[前i列][选了j个矩阵],分为选与不选当前格两种,选的时候可以连着前面的当做一个矩阵

    m == 2 的做法类比m == 1的做法,

    f[第1列选了前i个][第2列选了前j个][选了k个子矩阵] = 最大和

    对于当前的要选的子矩阵,选的情况有4种:

    1. 不选

    2. 选第一列

    3.选第二列

    3.i==j时两列可以看做一个矩阵

    代码:

     1 /***********************
     2 User:Mandy.H.Y
     3 Language:c++
     4 Problem:
     5 Algorithm: 
     6 ***********************/
     7 
     8 #include<bits/stdc++.h>
     9 
    10 using namespace std;
    11 
    12 const int maxn = 105;
    13 
    14 int n,m,K;
    15 int a[105][5];
    16 int sum[105][5];
    17 int dp[maxn][15];
    18 int f[maxn][maxn][15];
    19 
    20 template<class T>inline void read(T &x){
    21     x = 0;bool flag = 0;char ch = getchar();
    22     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
    23     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
    24     if(flag) x = -x;
    25 }
    26 
    27 template<class T>void putch(const T x){
    28     if(x > 9) putch(x / 10);
    29     putchar(x % 10 | 48);
    30 }
    31 
    32 template<class T>void put(const T x){
    33     if(x < 0) putchar('-'),putch(-x);
    34     else putch(x);
    35 }
    36 
    37 void file(){
    38     freopen("2331","r",stdin);
    39 }
    40 
    41 void readdata(){
    42     read(n);read(m);read(K);
    43     for(int i = 1;i <= n; ++ i){
    44         for(int j = 1;j <= m; ++ j){
    45             read(a[i][j]);
    46             sum[i][j] = sum[i - 1][j] + a[i][j];
    47         }
    48     }
    49 }
    50 
    51 void work(){
    52     if(m == 1){//其实这样没必要,因为可以当m == 2做只是第二列等于0; 
    53         for(int i = 1;i <= n; ++ i)
    54             for(int j = 1;j <= K; ++ j){ 
    55                 dp[i][j] = dp[i-1][j];//不选 
    56                 for(int l = 0;l <= i; ++ l)//l可以等于i,空矩阵也算子矩阵
    57                     dp[i][j] = max(dp[i][j],dp[l][j-1] + sum[i][1] - sum[l][1]);
    58             }
    59         put(dp[n][K]);
    60     } else {
    61         for(int i = 1;i <= n; ++ i)
    62             for(int j = 1;j <= n; ++ j)
    63                 for(int k = 1;k <= K; ++ k){
    64                     f[i][j][k] = max(f[i-1][j][k],f[i][j-1][k]);//不选 
    65                     for(int l = 0;l <= i; ++ l)//选第一列 
    66                         f[i][j][k] = max(f[i][j][k],f[l][j][k-1] + 
    67                                          sum[i][1] - sum[l][1]);
    68                     
    69                     for(int l = 0;l <= j;++ l)//选第二列 
    70                         f[i][j][k] = max(f[i][j][k],f[i][l][k-1] + 
    71                                          sum[j][2] - sum[l][2]);
    72                     
    73                     if(i == j)
    74                         for(int l = 0;l <= i; ++ l)//两列一起 
    75                             f[i][j][k] = max(f[i][j][k],f[l][l][k-1] + 
    76                                              sum[i][1] - sum[l][1] + 
    77                                              sum[j][2] - sum[l][2]);
    78                 }
    79         put(f[n][n][K]);
    80     } 
    81 }
    82 
    83 int main(){
    84 //    file();
    85     readdata();
    86     work();
    87     return 0;
    88 }
    O(n^3*k)
  • 相关阅读:
    [CTSC2008]网络管理
    [HNOI/AHOI2018]转盘
    [HAOI2015]树上染色
    [CTSC2017]吉夫特
    [CTSC2011]幸福路径
    Comet OJ
    2019各省省选试题选做
    HNOI2019 简要题解
    HNOI2019游记
    JOISC2019 简要题解
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11470109.html
Copyright © 2020-2023  润新知