返學(xué)費網(wǎng) > 培訓(xùn)機構(gòu) > 游戲設(shè)計交流中心
科技時代到來,優(yōu)異也隨之而來,我們會去關(guān)注NOIP2007矩陣取數(shù)游戲 PASCAL,pascal解矩陣取數(shù)游戲,求思路NOIP2007矩陣取數(shù)游戲,矩陣取數(shù)游戲(2007NOIP)求處理思路??,還可以通過NOIP2007矩陣取數(shù)游戲 PASCAL,pascal解矩陣取數(shù)游戲,求思路NOIP2007矩陣取數(shù)游戲,矩陣取數(shù)游戲(2007NOIP)求處理思路??進一步去來了解,接下來就跟隨作者一起去看看吧!
每次取兩端的最小值然后在按規(guī)則運算
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.
很簡單的動規(guī)啊 首先每一行可以獨立計算~ f[i,j]表示取走某一行從第i個到第j個的最佳值 最后一個取的肯定是i或者j 于是就得出上面那個轉(zhuǎn)移方程了
我們可以注意到,每一行都是獨立的,即我們可以把每一行都分別算完后最后將各行結(jié)果相加,有數(shù)據(jù)規(guī)???,需要用到高精度運算。由樣例1的解釋看,固守本分的一路作下去,最大會出現(xiàn)1000*2^80,需要編寫高精度乘法,提高了程序的空間復(fù)雜度。因此,我采取逆向思維,在每一層運算中先將2乘入,以下是我的方程:F[i,j]:=max{2*(data[i]+F[i+1,j]),2*(data[j]+F[i,j-1])}。F[i,j]表示從i到j(luò)這一段數(shù)據(jù)的最大值,其計算方法解釋如下:我們需要用L(從1到m)來控制i-j段的長度,每次i都從頭到尾走一遍,j=i+l-1。當(dāng)L=1,i=1時,j=1,F(xiàn)[1,1]=max{2*(data[1]+F[2,1]),2*(data[1]+F[1,0])},由于此時F[2,1]、F[1,0]值為0,所以L=1時數(shù)據(jù)最大值就是2*data[i],要注意的是,這里的data[i]將會是最后一個取走的元素。當(dāng)L=2,i=1時,j=2,F(xiàn)[1,2]=max{2*(data[1]+F[2,2]),2*(data[2]+F[1,1])},此時L=1時計算得的就要用上了;我們假設(shè)數(shù)據(jù)max都是前者,那么F[1,2]=2*(data[1]+F[2,2])=2*(data[1]+2*data[2])。在看一個,L=3,i=1時,j=3,同樣假設(shè),F(xiàn)[1,3]=2*(data[1]+2*(data[2]+2*data[3]))。如樣例1第一行數(shù)據(jù)的計算:F[1,3]=2*(1+2*(2+2*4))=1*2+2*2^2+4*2^3,這樣就可以逆向?qū)㈤L度為3的i-j段的最大值求出,最后的F[1,m]就是每行的最大值了。如此一來,我們只需要在做高精度加法的同時將數(shù)據(jù)左移1位。此題的高精度并非常規(guī)運算,因為我們本欲用于存儲數(shù)據(jù)的F本身是個二維數(shù)組了,因為我將F拓展為一個二維+一維的數(shù)組,二維用于狀態(tài)方程的定位,一維用于存儲高精度數(shù)。每計算完一行就將F[1,m][k]的每一位加入結(jié)果數(shù)組ans[k]。這樣,只需要用到2次高精度加法就可以將game AC了。
上文講述了NOIP2007矩陣取數(shù)游戲 PASCAL,pascal解矩陣取數(shù)游戲,求思路NOIP2007矩陣取數(shù)游戲,矩陣取數(shù)游戲(2007NOIP)求處理思路??,大致對NOIP2007矩陣取數(shù)游戲 PASCAL,pascal解矩陣取數(shù)游戲,求思路NOIP2007矩陣取數(shù)游戲,矩陣取數(shù)游戲(2007NOIP)求處理思路??有個簡單了解,如還需深了解請聯(lián)系作者。
只要一個電話
我們免費為您回電