zoukankan      html  css  js  c++  java
  • 【SCOI2005】 最大子矩阵 BZOJ 1084

    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

    思路

        看到题目:好难啊。。一点思路都没有。

        然后看到数据范围M<=2,你™在逗我?何必用矩形来吓人呢。。就是两个一维的最大子矩阵问题嘛!

        然后用f[i][j][k]表示第一列用到i,第二列用到j,已经有k个矩形的最大值。

        所以f[i][j][k]=max{f[i'-1][j][k-1]+sum[1][i'][i],f[i][j'-1][k-1]+sum[2][j'][j]}

        当i==j的时候还会有一个转移,就是两行一起形成一个矩形。

         f[i][i][k]=max{f[i'-1][i'-1][k-1]+sum[1][i'][i]+sum[2][i'][i]}

        其中sum[i][j][k]表示第i列从第j个数加到第k个数的和。

        还有一种特殊情况就是全都是负数,或者非负数的个数不够k的,就先选出所有的非负数,然后加上最大的几个负数就行了。

        可是数据里面好像没有这种情况TAT。。伐开森。

      

     1 #include <iostream>
     2 #include <cstring>
     3 #include <string>
     4 #include <cstdio>
     5 #include <cstdlib>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <queue>
     9 #include <stack>
    10 #include <map>
    11 #include <set>
    12 #include <list>
    13 #include <vector>
    14 #include <ctime>
    15 #include <functional>
    16 #define pritnf printf
    17 #define scafn scanf
    18 #define sacnf scanf
    19 #define For(i,j,k) for(int i=(j);i<=(k);(i)++)
    20 #define Clear(a) memset(a,0,sizeof(a))
    21 using namespace std;
    22 typedef unsigned int Uint;
    23 const int INF=0x3fffffff;
    24 ///==============struct declaration==============
    25 
    26 ///==============var declaration=================
    27 const int MAXN=110;
    28 int row,col,k,temp=0;
    29 int A[MAXN][10],Sum[MAXN][5];
    30 int f[MAXN][MAXN][15];
    31 ///==============function declaration============
    32 int cmp(int a,int b){return a>b;}
    33 ///==============main code=======================
    34 int main()
    35 {
    36 #define FILE__
    37 #ifdef FILE__
    38    freopen("input","r",stdin);
    39    freopen("output","w",stdout);
    40 #endif
    41    scanf("%d%d%d",&row,&col,&k);
    42    int Plus=0;
    43    for(int i=1;i<=row;i++)
    44       for(int j=1;j<=col;j++){
    45          scanf("%d",&A[i][j]);
    46          Sum[i][j]=Sum[i-1][j]+A[i][j];
    47          if (A[i][j]>=0){
    48             Plus++;
    49             temp+=A[i][j];
    50          }
    51       }
    52    for(int r1=1;r1<=row;r1++)
    53       for(int r2=1;r2<=row;r2++)
    54          for(int p=1;p<=k;p++){
    55             f[r1][r2][p]=max(f[r1][r2-1][p],f[r1-1][r2][p]);
    56             for(int NewR=1;NewR<=max(r1,r2);NewR++){
    57                if (NewR<=r1)
    58                   f[r1][r2][p]=max(f[r1][r2][p],f[NewR-1][r2][p-1]+Sum[r1][1]-Sum[NewR][1]);
    59                if (NewR<=r2)
    60                   f[r1][r2][p]=max(f[r1][r2][p],f[r1][NewR-1][p-1]+Sum[r2][2]-Sum[NewR][2]);
    61                if (r1==r2){
    62                   f[r1][r2][p]=max(f[NewR-1][NewR-1][p-1]+Sum[r1][1]-Sum[NewR][1]+Sum[r2][2]-Sum[NewR][2],f[r1][r2][p]);
    63                }
    64             }
    65          }
    66    if (Plus>=k)
    67      printf("%d
    ",f[row][row][k]);
    68    else{
    69       int Arr[MAXN*2];
    70       for(int i=1;i<=row;i++){
    71          Arr[i*2-1]=A[i][1];if (Arr[i*2-1]>0) Arr[i*2-1]=-INF;
    72          Arr[i*2]=A[i][2];if (Arr[i*2]>0) Arr[i*2]=-INF;
    73       }
    74       sort(Arr+1,Arr+1+row*2,cmp);
    75       for(int i=Plus+1;i<=k;i++)
    76          temp+=Arr[i-Plus];
    77       printf("%d
    ",temp);
    78    }
    79    return 0;
    80 }
    81 ///================fuction code====================
    BZOJ 1084
  • 相关阅读:
    [转]汇编语言的准备知识给初次接触汇编者 4
    Javascript实现页面跳转的几种方式收藏
    [转]汇编语言的准备知识给初次接触汇编者 1
    jQuery常用的函数的简单描述 便于查阅
    解决win7光驱驱动找不到的问题
    tar
    liunx64运行飞信的问题
    centos6禁用ipv6
    仍然是yum问题rhel6使用centos的yum源
    【MyBatis】使用MyBatis的分页组件PageHelper时,多表关联下使用别名查询时,前台传参过来,根据参数排序的解决方案
  • 原文地址:https://www.cnblogs.com/Houjikan/p/4323708.html
Copyright © 2011-2022 走看看