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

    [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

    又是一道DP题,由于看题太过迅速,竟然没有看清m<=2!!!(好气哦qaq)

    题解:

    既然在知道了m<=2的条件下,那么应该是可以想到,对m=1和m=2分别考虑

    (1)m=1的情况其实就是一个求k个最大字段和

    那么可以用一个二维数组f[i][j]表示到了第i位选取了j个字段

    那么转移就是分为不选第i位和选第i位的情况

    f[i][j]=f[i-1][j]

    f[i][j]=max(f[i][j],f[l-1][j-1]+sum[i]-sum[l])(1<=l<=i)

    (2)m=2的情况就是一个三维DP

    f[i][j][k]表示第一列选到第i行,第二列选到第j行,一共选了k个矩形

    那么转移分为四种第i和第j行都不选,选第i行,选第j行,同时选第i和第j行(前提i=j)

    那么具体的转移方程请见程序

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=110;
     4 int n,m,k,sum,ans;
     5 int a[N][3],sum1[N],sum2[N],f[N][N][12],g[N][12];
     6 int main(){
     7     scanf("%d%d%d",&n,&m,&k);
     8     for (int i=1;i<=n;++i)
     9         for (int j=1;j<=m;++j) 
    10             scanf("%d",&a[i][j]);
    11     for (int i=1;i<=n;++i) sum1[i]=sum1[i-1]+a[i][1];
    12     if (m==2) for (int i=1;i<=n;++i) sum2[i]=sum2[i-1]+a[i][2];
    13     if (m==1){
    14         for (int i=1;i<=k;++i) g[0][i]=0;
    15         for (int i=1;i<=n;++i)
    16             for (int j=1;j<=k;++j){
    17                 g[i][j]=g[i-1][j];
    18                 for (int l=1;l<=i;++l) g[i][j]=max(g[i][j],g[l-1][j-1]+sum1[i]-sum1[l-1]);
    19             }
    20         printf("%d",g[n][k]); return 0;
    21     }
    22     for (int i=0;i<=k;++i) f[0][0][i]=0;
    23     for (int i=1;i<=n;++i)
    24         for (int j=1;j<=n;++j)
    25             for (int l=1;l<=k;++l){
    26                 f[i][j][l]=max(f[i-1][j][l],f[i][j-1][l]);
    27                 for (int h=1;h<=i;++h)
    28                     f[i][j][l]=max(f[i][j][l],f[h-1][j][l-1]+sum1[i]-sum1[h-1]);
    29                 for (int h=1;h<=j;++h)
    30                     f[i][j][l]=max(f[i][j][l],f[i][h-1][l-1]+sum2[j]-sum2[h-1]);
    31                 if (i==j) for (int h=1;h<=i;++h) f[i][j][l]=max(f[i][j][l],f[h-1][h-1][l-1]+sum1[i]+sum2[j]-sum1[h-1]-sum2[h-1]);
    32             }
    33     printf("%d",f[n][n][k]);    
    34 }
    View Code
  • 相关阅读:
    [题解]POJ_1417_(并查集背包
    [题解]POJ_2912_(带权并查集
    [题解]luogu_P1502_窗口的星星(扫描线
    [题解/模板]POJ_1733_Pairty game(带权并查集/扩展域
    [题解/模板]悬线法luogu_P1169_棋盘制作(悬线法
    [题解]luogu_P2059_卡牌游戏(状态设计/概率dp
    [题解]luogu_P2467_地精部落(思维dp
    「CJOJ2439」军队
    「LG2397」yyy loves Maths VI (mode)
    「LG2114」起床困难综合症
  • 原文地址:https://www.cnblogs.com/logic-yzf/p/7654383.html
Copyright © 2011-2022 走看看