Bzoj1084: [SCOI2005]最大子矩阵

题目链接
一开始没仔细看题TAT,后来发现“1≤m≤2”。。。
这提示我萌什么?
我把解法分为m=1和m=2两种情况
首先,sum[i,j]为第j列的前缀和,即表示第j列前i行各个数字的和
①当m=1 时:
   用f[i,j]表示前i个数,取了j个矩阵的最优值
   目标状态:f[n,k]
   状态转移:f[i,j]=max(f[i-1,j],f[k,j-1]+sum[i,1]-sum[k,1])(0<=k<=i-1)
②当m=2 时:
   用w[i,j,k]表示第一列取到第i个数,第二列取到第j个数,取了k个矩阵的最优值
   目标状态:f[n,n,k]
   状态转移:f[i,j,k]=max(w[i-1,j,k],w[i,j-1,k]//不取
                   w[ii,j,k-1]+sum[i,1]-sum[ii,1] , w[i,jj,k-1]+sum[j,2]-sum[jj,2]//分别在两列取
                 (当i=j时)w[ii,ii,k-1]+sum[i,1]+sum[i,2]-sum[ii,1]-sum[ii,2]//在两列都取)
【Code】:
var
  i,j,k,n,m,t,ii,jj:integer;
  tot,cnt,ans:longint;
  sum:array[0..110,0..2]of longint;
  f:array[0..110,0..12]of longint;
  w:array[0..110,0..110,0..12] of longint;
function max(i,j:longint):longint;
begin
  if i>j then exit(i);exit(j);
end;
begin
  readln(n,m,k);
  fillchar(sum,sizeof(sum),0);
  for i:=1 to n do begin
    for j:=1 to m do begin
      read(t);
      sum[i,j]:=sum[i-1,j]+t;
    end;
    readln;
  end;
  if m=1 then begin
    fillchar(f,sizeof(f),0);
    for i:=0 to n+1 do f[i,0]:=0;
    for i:=1 to n do
      for cnt:=1 to k do begin
        f[i,cnt]:=f[i-1,cnt];
        for j:=0 to i-1 do
          f[i,cnt]:=max(f[i,cnt],f[j,cnt-1]+sum[i,1]-sum[j,1]);
      end;
      writeln(f[n,k]);
  end
  else begin
    fillchar(w,sizeof(w),0);
    for i:=1 to n do
      for j:=1 to n do begin
        w[i,j,0]:=0;
        for cnt:=1 to k do begin
          w[i,j,cnt]:=max(w[i-1,j,cnt],w[i,j-1,cnt]);
          for ii:=0 to i-1 do
            w[i,j,cnt]:=max(w[i,j,cnt],w[ii,j,cnt-1]+sum[i,1]-sum[ii,1]);
          for jj:=0 to j-1 do
            w[i,j,cnt]:=max(w[i,j,cnt],w[i,jj,cnt-1]+sum[j,2]-sum[jj,2]);
          if i=j then
            for ii:=0 to i-1 do
              w[i,j,cnt]:=max(w[i,j,cnt],w[ii,ii,cnt-1]+sum[i,1]+sum[i,2]-sum[ii,1]-sum[ii,2]);
        end
      end;
    writeln(w[n,n,k])
  end
end.
posted @ 2015-07-15 17:05  Vincent_hwh  阅读(48)  评论(0编辑  收藏