科技时代到来,优异也随之而来,我们会去关注NOIP2007矩阵取数游戏 PASCAL,pascal解矩阵取数游戏,求思路NOIP2007矩阵取数游戏,矩阵取数游戏(2007NOIP)求處理思路??,还可以通过NOIP2007矩阵取数游戏 PASCAL,pascal解矩阵取数游戏,求思路NOIP2007矩阵取数游戏,矩阵取数游戏(2007NOIP)求處理思路??进一步去来了解,接下来就跟随作者一起去看看吧!
每次取两端的最小值然后在按规则运算
program gjid;const up=1000000;type arr=array[0..100]of longword;var n,m:longint; a:array[1..81]of longint; f:array[-1..81,-1..81]of arr; ans,maxf:arr; p:array[1..80]of arr;procedure init;var i:longint;begin for i:=1 to m do read(a[i]); readln;end;{init}function add(a,b:arr):arr;var i,j,x:longint; c:arr;begin x:=0; i:=1; fillchar(c,sizeof(c),0); while (i<=a[0])or(i<=b[0]) do begin c[i]:=a[i]+b[i]+x; x:=c[i] div up; c[i]:=c[i] mod up; inc(i); end;{WHILE} if x>0 then begin c[0]:=i; c[i]:=x; end else c[0]:=i-1; add:=c;end;{add}function mul(k:longint;a:arr):arr;var x:longword; i:longint;begin x:=0; for i:=1 to a[0] do begin a[i]:=a[i]*k+x; x:=a[i] div up; a[i]:=a[i] mod up; end;{FOR_i} while x<>0 do begin inc(a[0]); a[a[0]]:=x mod up; x:=x div up; end;{WHILE} mul:=a;end;{mul}function max(a,b:arr):arr;var i:longint;begin if a[0]>b[0] then exit(a) else if a[0]<b[0] then exit(b) else for i:=a[0] downto 1 do if a[i]>b[i] then exit(a) else if b[i]>a[i] then exit(b); exit(b);end;{max}procedure dp;var i,j:longint; c,d:arr;begin fillchar(maxf,sizeof(maxf),0); fillchar(f,sizeof(f),0); for i:=0 to m do for j:=m+1 downto i+1 do begin c:=add(f[i-1,j],mul(a[i],p[i-j+m+1])); d:=add(f[i,j+1],mul(a[j],p[i-j+m+1])); f[i,j]:=max(c,d); end;{FOR_j} for i:=1 to m-1 do maxf:=max(maxf,f[i,i+1]);end;{dp}procedure calc;var i:longint;begin p[1][0]:=1; p[1][1]:=2; for i:=2 to 80 do p[i]:=mul(2,p[i-1]); for i:=1 to n do begin init; dp; ans:=add(ans,maxf); end;{FOR_i}end;{calc}procedure print;var i:longint;begin write(ans[ans[0]]); for i:=ans[0]-1 downto 1 do begin if ans[i]<100000 then write('0'); if ans[i]<10000 then write('0'); if ans[i]<1000 then write('0'); if ans[i]<100 then write('0'); if ans[i]<10 then write('0'); write(ans[i]); end;{FOR_i} writeln;end;{print}begin{main} readln(n,m); calc; print;end.
很简单的动规啊 首先每一行可以独立计算~ f[i,j]表示取走某一行从第i个到第j个的最佳值 最后一个取的肯定是i或者j 于是就得出上面那个转移方程了
我们可以注意到,每一行都是独立的,即我们可以把每一行都分别算完后最后将各行结果相加,有数据规模看,需要用到高精度运算。由样例1的解释看,固守本分的一路作下去,最大会出现1000*2^80,需要编写高精度乘法,提高了程序的空间复杂度。因此,我采取逆向思维,在每一层运算中先将2乘入,以下是我的方程:F[i,j]:=max{2*(data[i]+F[i+1,j]),2*(data[j]+F[i,j-1])}。F[i,j]表示从i到j这一段数据的最大值,其计算方法解释如下:我们需要用L(从1到m)来控制i-j段的长度,每次i都从头到尾走一遍,j=i+l-1。当L=1,i=1时,j=1,F[1,1]=max{2*(data[1]+F[2,1]),2*(data[1]+F[1,0])},由于此时F[2,1]、F[1,0]值为0,所以L=1时数据最大值就是2*data[i],要注意的是,这里的data[i]将会是最后一个取走的元素。当L=2,i=1时,j=2,F[1,2]=max{2*(data[1]+F[2,2]),2*(data[2]+F[1,1])},此时L=1时计算得的就要用上了;我们假设数据max都是前者,那么F[1,2]=2*(data[1]+F[2,2])=2*(data[1]+2*data[2])。在看一个,L=3,i=1时,j=3,同样假设,F[1,3]=2*(data[1]+2*(data[2]+2*data[3]))。如样例1第一行数据的计算:F[1,3]=2*(1+2*(2+2*4))=1*2+2*2^2+4*2^3,这样就可以逆向将长度为3的i-j段的最大值求出,最后的F[1,m]就是每行的最大值了。如此一来,我们只需要在做高精度加法的同时将数据左移1位。此题的高精度并非常规运算,因为我们本欲用于存储数据的F本身是个二维数组了,因为我将F拓展为一个二维+一维的数组,二维用于状态方程的定位,一维用于存储高精度数。每计算完一行就将F[1,m][k]的每一位加入结果数组ans[k]。这样,只需要用到2次高精度加法就可以将game AC了。
上文讲述了NOIP2007矩阵取数游戏 PASCAL,pascal解矩阵取数游戏,求思路NOIP2007矩阵取数游戏,矩阵取数游戏(2007NOIP)求處理思路??,大致对NOIP2007矩阵取数游戏 PASCAL,pascal解矩阵取数游戏,求思路NOIP2007矩阵取数游戏,矩阵取数游戏(2007NOIP)求處理思路??有个简单了解,如还需深了解请联系作者。