bzoj 1084: [SCOI2005]最大子矩阵 dp

Description

这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。

Input

第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。

Output

只有一行为k个子矩阵分值之和最大为多少。


我们看到由于m最大只有2,所以就可以用二维来搞定。用f[i,j,k]表示第一列前i个第二列前j个选k个矩形的最大值。然后枚举前面的就好了。记得i=j的时候要分类讨论。

再不懂的看代码。

代码:

var
  n,m,p,x,ans,i,j:longint;
  s:array[1..2,0..200] of longint;

function max(x,y:longint):longint;
begin
  if x>y then exit(x)
         else exit(y);
end;

procedure work2;
var
  i,j,k,l:longint;
  f:array[0..200,0..200,0..10] of longint;
begin
  fillchar(f,sizeof(f),0);
  for k:=1 to p do
    for i:=1 to n do
      for j:=1 to n do
      begin
        f[i,j,k]:=max(f[i-1,j,k],f[i,j-1,k]);
        for l:=1 to i do
          f[i,j,k]:=max(s[1,i]-s[1,l-1]+f[l-1,j,k-1],f[i,j,k]);
        for l:=1 to j do
          f[i,j,k]:=max(s[2,j]-s[2,l-1]+f[i,l-1,k-1],f[i,j,k]);
        if i=j then
          for l:=1 to i do
            f[i,j,k]:=max(s[1,i]-s[1,l-1]+s[2,i]-s[2,l-1]+f[l-1,l-1,k-1],f[i,j,k]);
        if f[i,j,k]>ans then ans:=f[i,j,k];
      end;
end;

procedure work1;
var
  i,j,k:longint;
  g:array[0..100,0..10] of longint;
begin
  fillchar(g,sizeof(g),0); 
  for k:=1 to p do
    for i:=1 to n do
    begin
      g[i,k]:=g[i-1,k];
      for j:=1 to i do
        g[i,k]:=max(g[i,k],s[1,i]-s[1,j-1]+g[j-1,k-1]);
      if g[i,k]>ans then ans:=g[i,k];
    end;
end;

begin
  readln(n,m,p);
  for i:=1 to n do
    for j:=1 to m do
    begin
      read(x);
      s[j,i]:=s[j,i-1]+x;
    end;
  if m=1
    then work1
    else work2;
  writeln(ans);
end.


你可能感兴趣的:(bzoj 1084: [SCOI2005]最大子矩阵 dp)