zoukankan      html  css  js  c++  java
  • bzoj 1084: [SCOI2005]最大子矩阵

    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<=2,那么肯定是要用上的。。。
    如果m==1,那么就是一个裸的序列划分型dp,设dp[i][k],表示到了第i位,选了k个的最大值(i不一定要选)
    如果m==2,那么我们多加一维就是了,设dp[i][j][k],表示第一列到了i,第二列到了j,选了k个矩阵的最大值。。。(i,j都不一定要选)
    我们首先考虑每列单独取矩阵的情况,就是对每列做一遍划分型dp。。。
    然后对于i==j的情况,表示是两列同时取矩形的情况,因为要选矩形,所以两列的位置要一样。。。
    也是一个类似的划分型dp,即从之前的dp[la][la][k-1]转移过来。。。用个前缀和优化即可。。。
    // MADE BY QT666
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=100050;
    int dp[200][200][15],f[200][15],a[200][200];
    int sum[N],sum2[N],n,m,k;
    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]);
      if(m==1){
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i][1];
        for(int p=1;p<=k;p++){
          for(int i=1;i<=n;i++){
    	f[i][p]=max(f[i-1][p],f[i][p]);
    	for(int j=0;j<i;j++){
    	  f[i][p]=max(f[i][p],f[j][p-1]+sum[i]-sum[j]);
    	}
          }
        }
        int ans=0;
        for(int i=0;i<=k;i++) ans=max(ans,f[n][i]);
        printf("%d
    ",ans);
      }
      else{
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i][1];
        for(int i=1;i<=n;i++) sum2[i]=sum2[i-1]+a[i][2];
        for(int p=1;p<=k;p++){
          for(int i=0;i<=n;i++){
    	for(int j=0;j<=n;j++){
    	  dp[i][j][p]=max(dp[i][j][p],max(dp[max(0,i-1)][j][p],dp[i][max(j-1,0)][p]));
    	  dp[i][j][p]=max(dp[i][j][p],dp[max(i-1,0)][max(j-1,0)][p]);
    	  for(int la=0;la<i;la++) dp[i][j][p]=max(dp[i][j][p],dp[la][j][p-1]+sum[i]-sum[la]);
    	  for(int la=0;la<j;la++) dp[i][j][p]=max(dp[i][j][p],dp[i][la][p-1]+sum2[j]-sum2[la]);
    	  if(i==j){
    	    for(int la=0;la<i;la++)
    	      dp[i][j][p]=max(dp[i][j][p],dp[la][la][p-1]+sum[i]-sum[la]+sum2[j]-sum2[la]);
    	  }
    	}
          }
        }
        int ans=0;
        for(int p=0;p<=k;p++) ans=max(ans,dp[n][n][p]);
        printf("%d
    ",ans);
      }
      return 0;
    }
  • 相关阅读:
    L2-004. 这是二叉搜索树吗?*
    L2-001. 紧急救援(最短路的变形)*
    L2-002. 链表去重(数组模拟)
    L1-028. 判断素数
    Linux相关
    2016ICPC-大连 A Simple Math Problem (数学)
    2016ICPC-大连 Convex (几何)
    2016ICPC-大连 To begin or not to begin (简单思维)
    TC704div2 C ModEquationEasy 矩阵快速幂+dp
    poj 3150 Cellular Automaton 矩阵快速幂
  • 原文地址:https://www.cnblogs.com/qt666/p/7435901.html
Copyright © 2011-2022 走看看