bzoj 1084: [SCOI2005]最大子矩阵

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
ACTY真神牛!!!(大家可以去bzoj上搜搜)
——————以下题解————————
m最大只有2
状压吧,用0,1,2,3,4表示一行的状态
0:表示一个都不选
1:表示选左边一个
2:表示选右边一个
3:表示2个作为一个整体选
4:表示2个分开来选
DP的转移就不多说了。。。
代码写得有些难看,忍一忍吧。。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int Min=-2000000000;
int n,m,v,k,i,j,l,ans,a[105][3],f[105][15][5];
int main()
{
    scanf("%d%d%d",&n,&m,&v);
    for(i=1;i<=n;i++)
     for(j=1;j<=m;j++)
     scanf("%d",&a[i][j]);
    for(i=1;i<=n;i++)
     for(j=0;j<=v;j++)
      for(k=0;k<=4;k++)
      f[i][j][k]=Min;
    f[1][0][0]=0;
    f[1][1][1]=a[1][1];
    f[1][1][2]=a[1][2];
    f[1][1][3]=a[1][1]+a[1][2];
    f[1][2][4]=a[1][1]+a[1][2];
    for(i=1;i<n;i++)
     for(j=0;j<=v;j++)
     {
         if(m==1)
         {
             for(k=0;k<=1;k++) f[i+1][j][0]=max(f[i+1][j][0],f[i][j][k]);
             f[i+1][j][1]=max(f[i+1][j][1],f[i][j][1]+a[i+1][1]);
             f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][1]+a[i+1][1]);
             f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][0]+a[i+1][1]);
             //cout<<f[4][3][1]<<' '<<i<<' '<<j<<' '<<f[i][j][0]<<' '<<f[i][j][1]<<endl;
         } else
         {
             //0
             for(k=0;k<=4;k++) f[i+1][j][0]=max(f[i+1][j][0],f[i][j][k]);
             //1
             f[i+1][j][1]=max(f[i+1][j][1],f[i][j][1]+a[i+1][1]);
             f[i+1][j][1]=max(f[i+1][j][1],f[i][j][4]+a[i+1][1]);
             f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][1]+a[i+1][1]);
             f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][0]+a[i+1][1]);
             f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][4]+a[i+1][1]);
             //2
             f[i+1][j][2]=max(f[i+1][j][2],f[i][j][2]+a[i+1][2]);
             f[i+1][j][2]=max(f[i+1][j][2],f[i][j][4]+a[i+1][2]);
             f[i+1][j+1][2]=max(f[i+1][j+1][2],f[i][j][0]+a[i+1][2]);
             f[i+1][j+1][2]=max(f[i+1][j+1][2],f[i][j][2]+a[i+1][2]);
             f[i+1][j+1][2]=max(f[i+1][j+1][2],f[i][j][4]+a[i+1][2]);
             //3
             f[i+1][j][3]=max(f[i+1][j][3],f[i][j][3]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+1][3]=max(f[i+1][j+1][3],f[i][j][0]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+1][3]=max(f[i+1][j+1][3],f[i][j][3]+a[i+1][1]+a[i+1][2]);
             //4
             f[i+1][j][4]=max(f[i+1][j][4],f[i][j][4]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+1][4]=max(f[i+1][j+1][4],f[i][j][1]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+1][4]=max(f[i+1][j+1][4],f[i][j][2]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][0]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][1]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][2]+a[i+1][1]+a[i+1][2]);
             f[i+1][j+2][4]=max(f[i+1][j+2][4],f[i][j][4]+a[i+1][1]+a[i+1][2]);
         }
     }
    ans=max(f[n][v][0],f[n][v][1]);
    if(m==2)
    for(i=2;i<=4;i++)
    ans=max(ans,f[n][v][i]);
    cout<<ans;
    return 0;
}

 

posted @ 2016-05-14 21:19  lwq12138  阅读(166)  评论(0编辑  收藏  举报