zoukankan      html  css  js  c++  java
  • BZOJ(6) 1084: [SCOI2005]最大子矩阵

    1084: [SCOI2005]最大子矩阵

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3566  Solved: 1785
    [Submit][Status][Discuss]

    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

    HINT

     

    Source

    思路:

    可以把m=1和m=2分开处理。

    当m=1时,有:f[i][k]表示到前i个数为止,选k的子矩阵的最优解。

    那么第i个数有选和不选两种情况

      不选:f[i][k]=max(f[i][k],f[i-1][k]);

      选:f[i][k]=max(f[i][k],f[q][k-1]+sum[i][1]-sum[q][1])

    当m=2时,有:g[k][i][j]表示左列到前i个,右列到前j个数为止,选出k个子矩阵的最优解。

    可先分开考虑,对于每一列有选和不选两种情况。

    然后当i==j时,考虑两列同时选和不选两种情况。

      有:

    g[j][i1][i2]=max(g[j][i1-1][i2],g[j][i1][i2]);

    g[j][i1][i2]=max(g[j][i1][i2-1],g[j][i1][i2]);

    g[j][i1][i2]=max(g[j-1][q][i2]+sum[i1][1]-sum[q][1],g[j][i1][i2]);

    g[j][i1][i2]=max(g[j-1][i1][q]+sum[i2][2]-sum[q][2],g[j][i1][i2]);
    g[j][i1][i2]=max(g[j-1][q][q]+sum[i1][1]-sum[q][1]+sum[i2][2]-sum[q][2],g[j][i1][i2]);
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,m,k;
    int sum[103][3];
    int a[103][3],f[103][103],g[103][103][103];
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                sum[i][j]=sum[i-1][j]+a[i][j];
            }
        /*for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cout<<sum[i][j]<<" ";
            }
            cout<<endl;
        }*/
        if(m==1){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=k;j++){
                    f[i][j]=max(f[i-1][j],f[i][j]);
                    for(int q=0;q<i;q++)
                        f[i][j]=max(f[i][j],f[q][j-1]+sum[i][1]-sum[q][1]);
                }
            }
            cout<<f[n][k];
        }
        else if(m==2){
            for(int i1=1;i1<=n;i1++)
                for(int i2=1;i2<=n;i2++)
                    for(int j=1;j<=k;j++){
                        g[j][i1][i2]=max(g[j][i1-1][i2],g[j][i1][i2]);
                        g[j][i1][i2]=max(g[j][i1][i2-1],g[j][i1][i2]);
                        for(int q=0;q<i1;q++)
                            g[j][i1][i2]=max(g[j-1][q][i2]+sum[i1][1]-sum[q][1],g[j][i1][i2]);
                        for(int q=0;q<i2;q++)
                            g[j][i1][i2]=max(g[j-1][i1][q]+sum[i2][2]-sum[q][2],g[j][i1][i2]);
                        if(i1==i2)
                            for(int q=0;q<i1;q++)
                                g[j][i1][i2]=max(g[j-1][q][q]+sum[i1][1]-sum[q][1]+sum[i2][2]-sum[q][2],g[j][i1][i2]);
                    //    cout<<g[j][i1][i2]<<"-->";
                    }
            cout<<g[k][n][n];
        }
    }
    /*
    3 2 2
    1 -3
    2 3
    -2 3
    */
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    H5页面跳到安卓APP和iosAPP
    JS location.href传参及接受参数
    获取当前日期及对应星期
    前端获取当前一周时间 数组形式
    Java基础(四) Object 数组转成 String 数组
    定时任务cron表达式详解
    jquery如何删除数组中的一个元素?
    Mybatis Mapper.xml 需要查询返回List<String>
    oracle的 listagg() WITHIN GROUP () 行转列函数的使用
    如何修改Oracle中表的字段长度?
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/9189941.html
Copyright © 2011-2022 走看看