如何做取1005矩阵的问题?

温馨提示:高精度计算,压位,DP,分而治之

Dp: f [I,j]表示这条线左侧到第I个位置,右侧到第J个位置时的最大得分。传递方程为:f [I,j]: = max (f [I-1,j]+a[I-1]*(2的n次方),f。

如何理解传递方程;

例如,有一些矩阵:

a1,a2,a3……安

B3 B2 b 1...BN有n列,但只有2行(这里考虑写,只列出2行,2行以上可以证明)。

假设上述矩阵的最大得分为:a 1 * 2+b 1 * 2+A2 * 22+B2 * 22...+an * 2n+bn * 2n。将这个公式进行变换,分别提取AN和BN,结果转化为A1 * 2+A2。我们可以看看这个公式,发现A1 * 2+A2 * 22...+An * 2n其实就是A1,A2,A3的最高分...安在第一行,而B1 * 2+B2 * 22...+BN * 2n也是第二行B652。也就是说,矩阵的最大得分实际上是每一行的最大得分之和,每一行的访问都不会与其他行相关或冲突。因此,矩阵检索的最大得分被分解为行检索的最大得分。只要求出每行的最大得分,然后求和,就可以得到矩阵的最大得分。

我们再来看单行取数问题的解法。首先,让函数maxgame (i,j) (i

const ma = 10000;//按到十进制

类型arr=array[0..80]的憧憬;//这是一个高精度。

变量f:数组[-1..82,-1..第82段];

a:数组[0..81,0..longint的81];

s2:数组[0..arr[80];

I,j,k,n,m:longint;

ss,sum,a1,a2,a3,a4:arr;

函数max(a,b:arr):arr;

var z:longint;

开始

如果a[0]& gt;b[0]然后退出(a);

如果b[0]& gt;a[0]然后退出(b);

对于z:=a[0]向下到1 do

开始

如果a[z]& gt;b[z]然后退出(a);

如果b[z]& gt;a[z]然后退出(b);

结束;

退出(a);

结束;

//高精度比较尺寸

function plus(a,b:arr):arr;

var z,l:longint;

开始

如果a[0]& gt;b[0]那么l:=a[0]否则l:= b[0];

如果l=0那么l:= 1;

对于z:=1到l do

开始

a[z+1]:= a[z+1]+(a[z]+b[z])div ma;

a[z]:=(a[z]+b[z])mod ma;

结束;

加:= a;

如果a[l+1]& lt;& gt0然后加[0]:=l+1 else加[0]:= l;//处理最高有效位

结束;

//高精度加法

函数乘法(b:longint;答:arr):arr;

var l,z:longint;

开始

l:= a[0];

如果l=0那么l:= 1;

对于z:=1到l do

a[z]:= a[z]* b;

对于z:=1到l do

开始

a[z+1]:= a[z+1]+a[z]div ma;

a[z]:= a[z]mod ma;

结束;

而a[l+1]& lt;& gt0 do

开始

Inc(l);

a[l+1]:= a[l]div ma;

a[l]:= a[l]mod ma;

结束;

//处理最高有效位

乘法:= a;

乘法[0]:= l;

结束;

//高精度乘法

过程初始化;

var i,j:longint;

开始

readln(n,m);

对于i:=1到n do

开始

对于j:=1到m do

read(a[i,j]);

readln

结束;

结束;

程序变更;

开始

fillchar(a,sizeof(a),0);

fillchar(f,sizeof(f),0);

fillchar(sum,sizeof(sum),0);

结束;

程序工作;

var i,j:longint;

开始

S2[1][1]:= 2;

S2[1][0]:= 1;

for i:=2 to m do s2[i]:=multiply(2,S2[I-1]);

结束;

主程序;

var i,j,k:longint;

开始

对于k:=1到n do

开始

对于i:=0到m do

对于j:=m+1向下到i+1 do

开始

a1:=multiply(a[k,i],S2[I+m-j+1]);

a2:=multiply(a[k,j],S2[I+m-j+1]);

a3:=plus(f[i-1,j],a 1);

a4:=plus(f[i,j+1],a2);

f[i,j]:=max(a3,a4);

结束;

ss:=f[0,1];

对于i:=1到m-1 do

ss:=max(ss,f[i,I+1]);

sum:=plus(sum,ss);

结束;

结束;

程序打印f;

var I:longint;

开始

write(sum[sum[0]]);

for i:=sum[0]-1向下到1 do

开始

if sum[I]& lt;10然后写(' 000 ');

if(sum[I]& gt;=10)和(sum[I]& lt;100)然后写(' 00 ');

if(sum[I]& gt;=100)和(sum[I]& lt;1000)然后写(' 0 ');

write(sum[I]);

结束;

writeln

结束;

开始

改变;

init

工作;

主要;

printf

结束。