program NDK1206; var n,m:longint; a:array [1..50,1..50] of longint; f:array [0..50,0..50,0..50,0..50] of longint; procedure init; var i,j:longint; begin readln(m,n); for i:=1 to m do begin for j:=1 to n do read(a[i,j]); readln; end; end; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; procedure main; var i,j,k,l:longint; begin for i:=1 to m do begin for j:=1 to n do begin for k:=1 to m do begin for l:=1 to n do begin if (i<>k) or (j<>l) then f[i,j,k,l]:=max(max(f[i-1,j,k-1,l],f[i,j-1,k,l-1]),max(f[i-1,j,k,l-1],f[i,j-1,k-1,l]))+a[i,j]+a[k,l];//f[i,j,k,l]表示传到i行j列和回传到k行l列所能取得的最大值,因为一项是从左上传到右下,另一项是从右下传到左上,所以行数和列数不能相等(即不能在一个格子重合) end; end; end; end; end; begin assign(input,'NDK1206.in'); reset(input); assign(output,'NDK1206.out'); rewrite(output); init; main; writeln(f[m-1,n,m,n-1]);//f[m,n,m,n]这一项必定不存在,因为之前我们要求行数或列数不能相等,因此目标即为行数和列数不能相等的前一项,即f[m-1,n,m,n-1] close(input); close(output); end.