zoukankan      html  css  js  c++  java
  • [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
     

    Solution

    这道题作为一道省选DP来讲的,偏简单了一些.
    但是还是有一点思维难度的.
    拿到先看 m , m 只有 1 和 2 ?
    所以先打了一下 m=1 的情况.
     

    状态定义:

    f[i][l] 表示到第 i 个点 用掉 l 个矩形的最大值.

    转移方程:

    for(pre 1--> i-1)

    f[i][l]=max(f[i-1][l],f[pre][l-1]+sum[pre-->i]); //sum 表示pre到i的元素值的和.

    于是 m=1 便有30 pts.

    然后再想 m=2 , 由 m=1 拓展?

    于是 定义状态 : f[ i ][ j ][ l ] 表示上面一列到了 i 下面一列到了 j 已选择 l 个矩阵的最大值.

    想了想,m=2有一下几种情况:

    1. 这个点我不做拓展  --> max( f[ i-1 ][ j-1 ][ l ] , f[ i-1 ][ j-1 ][ l ] ,f[ i ][ j-1 ][ l ] ) ; 

    2. 由上一列扩展一个小的 s*1 面积的

    3. 由上一列扩展一个小的 s*1 面积的

    4. 两列都作扩展 ,来一个 s*2 面积的

    于是乎,这道题的 DP 也自然就出来了.

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,k;
    int f1[105][11],f[105][105][11];
    int c[2][105],sum[2][105];
    
    void solve()    
    {
        for(int i=1;i<=n;i++)
        for(int l=1;l<=k;l++) 
            { 
                f1[i][l]=f1[i-1][l];
                for(int j=0;j<i;j++)
                f1[i][l]=max(f1[j][l-1]+sum[1][i]-sum[1][j],f1[i][l]);
            }
        cout<<f1[n][k];
        return;
    }
    
    
    int main()
    {
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        scanf("%d",&c[j][i]),sum[j][i]=sum[j][i-1]+c[j][i];
        if(m==1) {solve();return 0;}
        
        for(int l=1;l<=k;l++)
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) 
        {
                f[i][j][l]=max(f[i-1][j][l],f[i][j-1][l]);
                for(int pre=0;pre<i;pre++) f[i][j][l]=max(f[i][j][l],f[pre][j][l-1]+sum[1][i]-sum[1][pre]);
                for(int pre=0;pre<j;pre++) f[i][j][l]=max(f[i][j][l],f[i][pre][l-1]+sum[2][j]-sum[2][pre]);
                if(i==j)
                for(int pre=0;pre<i;pre++)
                f[i][j][l]=max(f[i][j][l],f[pre][pre][l-1]+sum[1][i]-sum[1][pre]+sum[2][j]-sum[2][pre]);
        }
        cout<<f[n][n][k];
    
        return 0;
    }

     

  • 相关阅读:
    AWK
    ftp自动上传下载文件脚本
    tostring格式化输出
    C#时间处理--DateTime和TimeSpan
    C#正则表达式语法规则详解
    C#常用的正则表达式
    C#字符串截取
    FTP操作
    [BZOJ2947]促销(Splay)
    [BZOJ1208]宠物收养所(Splay)
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9011370.html
Copyright © 2011-2022 走看看