如何做取1005矩阵的问题?
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
结束。