2019-2020年高中信息技術(shù) 全國(guó)青少年奧林匹克聯(lián)賽教案 動(dòng)態(tài)規(guī)劃實(shí)例分析及程序?qū)崿F(xiàn).doc
《2019-2020年高中信息技術(shù) 全國(guó)青少年奧林匹克聯(lián)賽教案 動(dòng)態(tài)規(guī)劃實(shí)例分析及程序?qū)崿F(xiàn).doc》由會(huì)員分享,可在線閱讀,更多相關(guān)《2019-2020年高中信息技術(shù) 全國(guó)青少年奧林匹克聯(lián)賽教案 動(dòng)態(tài)規(guī)劃實(shí)例分析及程序?qū)崿F(xiàn).doc(14頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
2019-2020年高中信息技術(shù) 全國(guó)青少年奧林匹克聯(lián)賽教案 動(dòng)態(tài)規(guī)劃實(shí)例分析及程序?qū)崿F(xiàn) 一、數(shù)字三角形 ?。▓D3.1-1)示出了一個(gè)數(shù)字三角形。 請(qǐng)編一個(gè)程序計(jì)算從頂至底的某處的一條路 徑,使該路徑所經(jīng)過(guò)的數(shù)字的總和最大。 ●每一步可沿左斜線向下或右斜線向下走; ●1<三角形行數(shù)≤100; ●三角形中的數(shù)字為整數(shù)0,1,…99; 輸入數(shù)據(jù): 由INPUT.TXT文件中首先讀到的是三角形的行數(shù)。 在例子中INPUT.TXT表示如下: 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 輸出數(shù)據(jù): 把最大總和(整數(shù))寫(xiě)入OUTPUT.TXT文件。 上例為: 30 ?。? 3?。? ?。浮。薄。? ?。病。贰。础。? 4?。怠。病。丁。? ?。▓D3.1-1) 二、算法分析 只要對(duì)該題稍加分析,就可以得出一個(gè)結(jié)論: 如果得到一條由頂至底的某處的一條最佳路徑,那么對(duì)于該路徑上的每一個(gè)中間點(diǎn)來(lái)說(shuō),由頂至該中間點(diǎn)的路徑所經(jīng)過(guò)的數(shù)字和也為最大。因此該題是一個(gè)典型的多階段決策最優(yōu)化 的問(wèn)題。 我們采用動(dòng)態(tài)規(guī)劃中的順推解法。按三角形的行劃分階段。若行數(shù)為n, 則可把問(wèn)題看作一個(gè)n-1個(gè)階段的決策問(wèn)題。從始點(diǎn)出發(fā),依順向求出第一階段、第二階段,……,第n-1階段中各決策點(diǎn)至始點(diǎn)的最佳路徑,最終求出始點(diǎn)到終點(diǎn)的最佳路徑。 設(shè): ?。鎘(Uk)━━從第k階段中的點(diǎn)Uk至三角形頂點(diǎn)有一條最佳路徑, 該路徑所經(jīng)過(guò)的 數(shù)字的總和最大,fk(Uk)表示為這個(gè)數(shù)字和; 由于每一次決策有兩個(gè)選擇,或沿左斜線向下,或沿右斜線向下,因此設(shè) ?。誯1━━k-1階段中某點(diǎn)Uk沿左斜線向下的點(diǎn); Uk2━━k-1階段中某點(diǎn)Uk沿右斜線向下的點(diǎn); dk(Uk1)━━k階段中Uk1的數(shù)字; dk(Uk2)━━k階段中Uk2的數(shù)字; 因而可寫(xiě)出順推關(guān)系式 ?。鎘(Uk)=max{fk-1(Uk)+dk(Uk1),fk-1(Uk)+dk(Uk2)} f0(U0)=0; ?。耍剑保?,3,4,……n 經(jīng)過(guò)一次順推,便可分別求出由頂至底N個(gè)數(shù)的N條路徑,在這N條路徑所經(jīng)過(guò)的N個(gè) 數(shù)字和中,最大值即為正確答案。 三、程序分析 根據(jù)上述順推關(guān)系,我們編寫(xiě)程序如下: Program ID1P1; Const Maxn = 100; Type Node = Record Val, Tot : Integer { 當(dāng)前格數(shù)字; 從[1,1]到當(dāng)前格的路徑所經(jīng)過(guò)的數(shù)字和 } End; Var List : Array [1..Maxn, 1..Maxn] of Node; { 計(jì)算表 } N, Max, { 行數(shù), 最大總和 } I, J : Integer; { 輔助變量 } Fi : Text; { 文件變量 } Procedure Init; Begin Assign(Fi, INPUT.TXT); { 文件名和文件變量連接 } Reset(Fi); { 文件讀準(zhǔn)備 } Readln(Fi, N); { 讀三角形行數(shù) } For i := 1 to N Do { 讀入三角形各格的數(shù)字 } For j := 1 to i Do Read(Fi, List[i, j].Val); Close(Fi) End; {init} Procedure Main; Begin List[1, 1].Tot := List[1, 1].Val; { 從[1,1]位置開(kāi)始往下順推 } For i := 2 to N Do For j := 1 to i Do Begin List[i, j].Tot := -1; { 從[1,1]至[i,j]的數(shù)字和初始化 } If (j <> 1) And (List[i - 1, j - 1].Tot + List[i, j].Val > List[i, j].Tot) Then List[i, j].Tot := List[i - 1, j - 1].Tot + List[i, j].Val; { 若從[i-1,j-1]選擇右斜線向下會(huì)使[1,1]至[i,j]的數(shù)字和最大,則決策該步 } If (j <> i) And (List[i - 1, j].Tot + List[i, j].Val > List[i, j].Tot) Then List[i, j].Tot := List[i - 1, j].Tot + List[i, j].Val { 若從[i-1,j]選擇左斜線向下會(huì)使[1,1]至[i,j]的數(shù)字和最大,則決策該步 } End; {for} Max := 1; { [1,1]至底行各點(diǎn)的N條路徑所經(jīng)過(guò)的數(shù)字和中,選擇最大的一個(gè)輸出 } For i := 2 to N Do If List[N, i].Tot > List[N, Max].Tot Then Max := i; Writeln(List[N, Max].Tot) { 輸出最大總和 } End; {main} Begin Init; { 讀入數(shù)字三角形 } Main { 求最大總和 } End.{main} 二、Problem : 打鼴鼠 Contents: 有個(gè)n*n個(gè)格子,在m個(gè)時(shí)間點(diǎn)上的不定格子里有數(shù)量不等的鼴鼠出現(xiàn),機(jī)器人每次只能向前后左右移動(dòng)一個(gè)格子,問(wèn)最多機(jī)器人能打多少鼴鼠? (n<=1000, m<=10000) Type: 動(dòng)態(tài)規(guī)劃 Difficulty: 2 Source: HNOIxx_day_*_* Solution : a) 記得學(xué)OI不到幾個(gè)月,高一剛上來(lái)就做的這道題..著實(shí)郁悶了半天,有一個(gè)思路是開(kāi)1000*1000 的數(shù)組亂搞…忘了可以過(guò)幾個(gè)來(lái)著.. b) 又翻到這道題的時(shí)候是2月份了..發(fā)現(xiàn) f[i]表示:如果機(jī)器人最后打死的老鼠是第i只,這種情況下機(jī)器人最多可以打死多少老鼠。就可以了,然后我赫然發(fā)現(xiàn)10^8 div 2次的若干基本操作是要TLE的 c) 鑒于這道題郁悶的理論時(shí)間復(fù)雜度無(wú)法優(yōu)化,我請(qǐng)教了朱老師,原來(lái)動(dòng)態(tài)規(guī)劃枚舉順序也有其優(yōu)化技巧,由于思路不是自己的,僅作簡(jiǎn)要介紹: a) (1).將更快、更容易“短路”的判斷放在前面 b) (2).將內(nèi)部循環(huán)(j的循環(huán))倒序,逼近最優(yōu)解 d) 我的計(jì)算機(jī)有點(diǎn)慢… 總分 = 100.0 第一題:mole 得分 = 100.0 用時(shí) = 7.16s mole-0(mole1.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 0.01s 空間 = 0.71M mole-1(mole2.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 0.01s 空間 = 0.71M mole-2(mole3.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 0.02s 空間 = 0.71M mole-3(mole4.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 0.98s 空間 = 0.71M mole-4(mole5.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 1.02s 空間 = 0.71M mole-5(mole6.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 1.00s 空間 = 0.71M mole-6(mole7.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 1.05s 空間 = 0.71M mole-7(mole8.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 1.02s 空間 = 0.71M mole-8(mole9.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 1.02s 空間 = 0.71M mole-9(mole10.In) 結(jié)果 = 正確 得分 = 10.0 用時(shí) = 1.02s 空間 = 0.71M [分析] 設(shè)第i只老鼠在第Ti個(gè)時(shí)刻出現(xiàn)在(xi, yi),T1<=T2<=T3<=…<=Tm。 假設(shè)機(jī)器人打死了L只老鼠,不妨設(shè)這些老鼠的編號(hào)是a1, a2, …, aL。顯然對(duì)于任意的i(1<=i<=L-1)都有T[ai+1]-T[ai]>=|x[ai+1]-x[ai]|+|y[ai+1]-y[ai]|。 f[i]表示:如果機(jī)器人最后打死的老鼠是第i只,這種情況下機(jī)器人最多可以打死多少老鼠。 可以列出方程: f[i] = max{f[j]+1, 1} 1<=j=|xi-xj|+|yi-yj| 最后求的答案就是max{f[i]}(1<=i<=m) 此算法時(shí)間復(fù)雜度為O(m2)。考慮到m<=10000,而時(shí)限只有1second,所以還必須進(jìn)行一些代碼優(yōu)化。 因?yàn)閖 f[i]) then f[i] := f[j]; f[i]:=f[i]+1; end; 它無(wú)疑是正確的。但是循環(huán)中的判斷語(yǔ)句大有文章可做:上面的代碼每次都鐵定至少要執(zhí)行3次減法、2次絕對(duì)值、1次比較運(yùn)算。這無(wú)疑是極度昂貴的操作代價(jià)。所以我們可以將(f[j]>f[i])這個(gè)比較“便宜”的判斷條件提到前面,變成如下形式: if (f[j]>f[i]) and (abs(x[i]-x[j]) + abs(y[i]-y[j])<=T[i]-T[j]) then 這樣做的好處是一旦f[j]<=f[i]就可以執(zhí)行“短路操作”(也就是說(shuō)后面那一大截速度很慢的操作都可以避免。不過(guò)編譯的時(shí)候一定要記得設(shè)成{$B+}) 實(shí)踐證明速度是快了不少??墒菍?duì)于1second的時(shí)限還是不能勝任。實(shí)戰(zhàn)游戲經(jīng)驗(yàn)告訴我們,機(jī)器人一般情況下不可能打完一只老鼠之后就跑到很遠(yuǎn)的地方去尋找新的獵物,肯定是一路上碰到一點(diǎn)老鼠就打一點(diǎn)。所以機(jī)器人相繼打的兩只老鼠的出現(xiàn)時(shí)間不可能相差太遠(yuǎn)。因此在方程 f[i] = max{f[j]+1, 1} 1<=j=|xi-xj|+|yi-yj| 之中,使得i達(dá)到最優(yōu)的j肯定不會(huì)和i差得太遠(yuǎn)。 同時(shí)在我們的判斷語(yǔ)句中: if (f[j]>f[i]) and (abs(x[i]-x[j]) + abs(y[i]-y[j])<=T[i]-T[j]) then f[i]越早接近最優(yōu)值,判斷語(yǔ)句的效率就越高(因?yàn)楹竺嬉唤乜梢员欢搪返簦?。因此我們將循環(huán)語(yǔ)句改成這樣的形式: for i := 1 to m do begin f[i] := 0; for j := i – 1 downto 1 do if (f[j]>f[i]) and (abs(x[i]-x[j]) + abs(y[i]-y[j])<=T[i]-T[j]) then f[i] := f[j]; f[i]:=f[i]+1; end; 實(shí)踐發(fā)現(xiàn),最慢的數(shù)據(jù)大概0.7s即可出解。 至此問(wèn)題解決了。 Program mole; {$B+} var f,t,x,y: array [1..10000] of longint; i,j,m,n,ans: longint; begin assign(input,mole.in); reset(input); readln(n,m); for i:= 1 to m do readln(t[i],x[i],y[i]); close(input); fillchar(f,sizeof(f),0); for i:= 1 to m do begin for j:= i-1 downto 1 do if (f[j]>f[i]) and (abs(x[i]-x[j])+abs(y[i]-y[j])<=t[i]-t[j]) then f[i]:=f[j]; inc(f[i]); if f[i]>ans then ans:=f[i]; end; assign(output,mole.out); rewrite(output); writeln(ans); close(output); END. 三、最大連續(xù)子序列 給出一個(gè)長(zhǎng)度為n 的整數(shù)序列A,找出i,j 使得那一段連續(xù)數(shù)之和最大。 第一行為n第二行為數(shù)列 輸入樣例 6 3 -5 2 4 -1 6 輸出樣例 11 [分析]: 設(shè)Fi表示Ai為最后一個(gè)元素的最大連續(xù)子序列。可得方程: Fi=max {Fi-1,0}+Ai 時(shí)間復(fù)雜度為O(n) Program zuidalianxuzixulie; var a,s:array [0..10000] of integer; i,j,n,max:integer; begin max:=0; assign(input,lxzxl.txt); reset(input); readln(n); fillchar(s,sizeof(s),0); for i:=1 to n do begin read(a[i]); s[i]:=s[i-1] + a[i]; end; close(input); for i:=1 to n do for j:=1 to n do if s[j] - s[i] > max then max := s[j] - s[i]; writeln(max); end. 四、街道問(wèn)題 在下圖中找出從左下角到右上角的最短路徑,每步只能向右方或上方走。 [分析] 這是一道簡(jiǎn)單而又典型的動(dòng)態(tài)規(guī)劃題,許多介紹動(dòng)態(tài)規(guī)劃的書(shū)與文章中都拿它來(lái)做例子。通常,書(shū)上的解答是這樣的: 按照?qǐng)D中的虛線來(lái)劃分階段,即階段變量k表示走過(guò)的步數(shù),而狀態(tài)變量xk表示當(dāng)前處于這一階段上的哪一點(diǎn)。這時(shí)的模型實(shí)際上已經(jīng)轉(zhuǎn)化成了一個(gè)特殊的多段圖。用決策變量uk=0表示向右走,uk=1表示向上走,則狀態(tài)轉(zhuǎn)移方程如下: (這里的row是地圖豎直方向的行數(shù)) 我們看到,這個(gè)狀態(tài)轉(zhuǎn)移方程需要根據(jù)k的取值分兩種情況討論,顯得非常麻煩。相應(yīng)的,把它代入規(guī)劃方程而付諸實(shí)現(xiàn)時(shí),算法也很繁。因而我們?cè)趯?shí)現(xiàn)時(shí),一般是不會(huì)這么做的,而代之以下面方法: (這里Distance表示相鄰兩點(diǎn)間的邊長(zhǎng)) 這樣做確實(shí)要比上面的方法簡(jiǎn)單多了,但是它已經(jīng)破壞了動(dòng)態(tài)規(guī)劃的本來(lái)面目,而不存在明確的階段特征了。如果說(shuō)這種方法是以地圖中的行(A、B、C、D)來(lái)劃分階段的話,那么它的"狀態(tài)轉(zhuǎn)移"就不全是在兩個(gè)階段之間進(jìn)行的了。 也許這沒(méi)什么大不了的,因?yàn)閷?shí)踐比理論更有說(shuō)服力。但是,如果我們把題目擴(kuò)展一下:在地圖中找出從左下角到右上角的兩條路徑,兩條路徑中的任何一條邊都不能重疊,并且要求兩條路徑的總長(zhǎng)度最短。這時(shí),再用這種"簡(jiǎn)單"的方法就不太好辦了。 如果非得套用這種方法的話,則最優(yōu)指標(biāo)函數(shù)就需要有四維的下標(biāo),并且難以處理兩條路徑"不能重疊"的問(wèn)題。 而我們回到原先"標(biāo)準(zhǔn)"的動(dòng)態(tài)規(guī)劃法,就會(huì)發(fā)現(xiàn)這個(gè)問(wèn)題很好解決,只需要加一維狀態(tài)變量就成了。即用xk=(ak,bk)分別表示兩條路徑走到階段k時(shí)所處的位置,相應(yīng)的,決策變量也增加一維,用uk=(xk,yk)分別表示兩條路徑的行走方向。狀態(tài)轉(zhuǎn)移時(shí)將兩條路徑分別考慮 在寫(xiě)規(guī)劃方程時(shí),只要對(duì)兩條路徑走到同一個(gè)點(diǎn)的情況稍微處理一下,減少可選的決策個(gè)數(shù): 從這個(gè)例子可以看出,合理地劃分階段和選擇狀態(tài)可以給解題帶來(lái)方便。 六、花店櫥窗 假設(shè)你想以最美觀的方式布置花店的櫥窗?,F(xiàn)在你有F束不同品種的花束,同時(shí)你也有至少同樣數(shù)量的花瓶被按順序擺成一行。這些花瓶的位置固定于架子上,并從1至V順序編號(hào),V是花瓶的數(shù)目,從左至右排列,則最左邊的是花瓶1,最右邊的是花瓶V?;ㄊ梢砸苿?dòng),并且每束花用1至F間的整數(shù)唯一標(biāo)識(shí)。標(biāo)識(shí)花束的整數(shù)決定了花束在花瓶中的順序,如果I<J,則令花束I必須放在花束J左邊的花瓶中。 例如,假設(shè)一束杜鵑花的標(biāo)識(shí)數(shù)為1,一束秋海棠的標(biāo)識(shí)數(shù)為2,一束康乃馨的標(biāo)識(shí)數(shù)為3,所有的花束在放入花瓶時(shí)必須保持其標(biāo)識(shí)數(shù)的順序,即:杜鵑花必須放在秋海棠左邊的花瓶中,秋海棠必須放在康乃馨左邊的花瓶中。如果花瓶的數(shù)目大于花束的數(shù)目。則多余的花瓶必須空置,且每個(gè)花瓶中只能放一束花。 每一個(gè)花瓶都具有各自的特點(diǎn)。因此,當(dāng)各個(gè)花瓶中放入不同的花束時(shí),會(huì)產(chǎn)生不同的美學(xué)效果,并以美學(xué)值(一個(gè)整數(shù))來(lái)表示,空置花瓶的美學(xué)值為零。 在上述例子中,花瓶與花束的不同搭配所具有的美學(xué)值,如下表所示。 花 瓶 1 2 3 4 5 1 (杜鵑花) 7 23 -5 -24 16 2 (秋海棠) 5 21 -4 10 23 3 (康乃馨) -21 5 -4 -20 20 例如,根據(jù)上表,杜鵑花放在花瓶2中,會(huì)顯得非常好看;但若放在花瓶4中則顯得十分難看。 為取得最佳美學(xué)效果,你必須在保持花束順序的前提下,使花束的擺放取得最大的美學(xué)值。如果有不止一種的擺放方式具有最大的美學(xué)值,則其中任何一直擺放方式都可以接受,但你只要輸出任意一種擺放方式。 (2)假設(shè)條件 1≤F≤100,其中F為花束的數(shù)量,花束編號(hào)從1至F。 F≤V≤100,其中V是花瓶的數(shù)量。 -50≤Aij≤50,其中Aij是花束i在花瓶j中的美學(xué)值。 (3)輸入 第一行包含兩個(gè)數(shù):F,V。 隨后的F行中,每行包含V個(gè)整數(shù),Aij 即為輸入文件中第(i+1 )行中的第j個(gè)數(shù)。 (4)輸出 一行是程序所產(chǎn)生擺放方式的美學(xué)值。 【樣例輸入1】 【樣例輸入2】 3 5 7 23 -5 -24 16 5 21 -4 10 23 -21 5 -4 -20 20 【樣例輸出1】 【樣例輸出2】 53 本題雖然是IOI’99中較為簡(jiǎn)單的一題,但其中大有文章可作。說(shuō)它簡(jiǎn)單,是因?yàn)樗行?,因此我們一眼便可看出這題應(yīng)該用動(dòng)態(tài)規(guī)劃來(lái)解決。但是,如何動(dòng)態(tài)規(guī)劃呢?如何劃分階段,又如何選擇狀態(tài)呢? <方法1> 以花束的編號(hào)來(lái)劃分階段。在這里,第k階段布置第k束花,共有F束花,有F+1個(gè)階段,增加第F+1階段是為了計(jì)算的方便;狀態(tài)變量xk表示第k束花所在的花瓶。而對(duì)于每一個(gè)狀態(tài)xk,決策uk就是第k+1束花放置的花瓶號(hào);最優(yōu)指標(biāo)函數(shù)fk(xk)表示從第k束花到第n束花所得到的最大美學(xué)值;A(i,j)是花束i插在花瓶j中的美學(xué)值,V是花瓶總數(shù),F是花的總數(shù)。 狀態(tài)轉(zhuǎn)移方程為 規(guī)劃方程為 邊界條件為: , 事實(shí)上這是一個(gè)虛擬的邊界。 最后要求的最大美學(xué)價(jià)值是 <方法2> 方法1的規(guī)劃方程中的允許決策空間:xk+1≤uk≤V-(F-k)+1 比較麻煩,因此有待改進(jìn)。還是以花束的編號(hào)來(lái)劃分階段,第k階段布置第k束花;狀態(tài)變量xk表示第k束花所在的花瓶;注意,這里我們考慮倒過(guò)來(lái)布置花瓶,即從第F束花開(kāi)始布置到第1束花。于是狀態(tài)變量uk表示第k-1束花所在的花瓶;最優(yōu)指標(biāo)fk(xk)表示從第一束花到第k束花所獲得的美學(xué)價(jià)值;A(i,j)是花束i插在花瓶j中的美學(xué)值,V是花瓶總數(shù),F是花的總數(shù)。則狀態(tài)轉(zhuǎn)移方程為: 規(guī)劃方程為: 增加的虛擬邊界條件為: 最后要求的最大美學(xué)價(jià)值是: 可以看出,這種方法實(shí)質(zhì)上和方法1沒(méi)有區(qū)別,但是允許決策空間的表示變得簡(jiǎn)單了。 <方法3> 以花瓶的數(shù)目來(lái)劃分階段,第k個(gè)階段決定花瓶k中是否放花;狀態(tài)變量xk表示前k個(gè)花瓶中放了多少花;而對(duì)于任意一個(gè)狀態(tài)xk,決策就是第xk束花是否放在第k個(gè)花瓶中,用變量uk=1或0來(lái)表示。最優(yōu)指標(biāo)函數(shù)fk(xk)表示前k個(gè)花瓶中插了xk束花,所能取得的最大美學(xué)值。注意,這里仍然是倒過(guò)來(lái)考慮。 狀態(tài)轉(zhuǎn)移方程為 規(guī)劃方程為 邊界條件為 三種不同的方法都成功地解決了問(wèn)題,只不過(guò)因?yàn)殡A段的劃分不同,狀態(tài)的表示不同,決策的選擇有多有少,所以算法的時(shí)間復(fù)雜度也就不同。 這個(gè)例子具有很大的普遍性。有很多的多階段決策問(wèn)題都有著不止一種的階段劃分方法,因而往往就有不止一種的規(guī)劃方法。有時(shí)各種方法所產(chǎn)生的效果是差不多的,但更多的時(shí)候,就像我們的例子一樣,兩種方法會(huì)在某個(gè)方面有些區(qū)別。所以,在用動(dòng)態(tài)規(guī)劃解題的時(shí)候,可以多想一想是否有其它的解法。對(duì)于不同的解法,要注意比較,好的算法好在哪里,差一點(diǎn)的算法差在哪里。從各種不同算法的比較中,我們可以更深刻地領(lǐng)會(huì)動(dòng)態(tài)規(guī)劃的構(gòu)思技巧。 七、航線設(shè)置 問(wèn)題描述:美麗的萊茵河畔,每邊都分布著N個(gè)城市,兩邊的城市都是唯一對(duì)應(yīng)的友好城市,現(xiàn)需要在友好城市開(kāi)通航線以加強(qiáng)往來(lái).但因?yàn)槿R茵河常年大霧,如果開(kāi)設(shè)的航線發(fā)生交叉現(xiàn)象就有可能出現(xiàn)碰船的現(xiàn)象.現(xiàn)在要求近可能多地開(kāi)通航線并且使航線不能相交! 假如你是一個(gè)才華橫溢的設(shè)計(jì)師,該如何設(shè)置友好城市間的航線使的航線數(shù)又最大又不相交呢? 分析:此問(wèn)題可以演化成求最大不下降序列來(lái)完成.源程序如下: program dongtai; {動(dòng)態(tài)規(guī)劃之友好城市航線設(shè)置問(wèn)題} var d:array[1..1000,1..4] of integer; i,j,k,n,L,p:integer; procedure print(L:integer); {打印結(jié)果} begin writeLn(最多可設(shè)置的航線數(shù)是 : ,k); repeat writeLn(d[L,1]:4,d[L,2]:4); {輸出可以設(shè)置航線的友好城市代碼} L:=d[L,4] untiL L=0 end; begin writeLn(輸入友好城市對(duì)數(shù): ); readLn(n); writeLn(輸入友好城市對(duì)(友好城市放在同一行:); {輸入} for i:=1 to n do readLn(d[i,1],d[i,2]); {D[I,1]表示起點(diǎn),D[I,2]表示終點(diǎn)} for i:=1 to n do begin d[i,3]:=1; {D[I,3]表示可以設(shè)置的航線條數(shù)} d[i,4]:=0 {D[I,4]表示后繼,即下一條航線從哪里開(kāi)始設(shè)置,為0表示不能設(shè)置下一條航線} end; for i:=n-1 downto 1 do {從倒數(shù)第二個(gè)城市開(kāi)始規(guī)劃} begin L:=0; p:=0; {L表示本城市后面可以設(shè)置的航線數(shù),P表示下條航線從哪個(gè)城市開(kāi)始} for j:=i+1 to n do {找出本城市后面可以設(shè)置的最大航線數(shù)和小條航線到底從哪個(gè)城市開(kāi)始設(shè)置} if (d[i,2] L) then {如果本城市I的終點(diǎn)小于后面城市的終點(diǎn)(即不相交)} {并且此城市后面可以設(shè)置的航線數(shù)大于L} begin L:=d[j,3]; {那么L等于城市J的可以設(shè)置航線數(shù)} p:=j {P等于可以設(shè)置下條航線的城市代碼} end; if L>0 then {如果本城市后面總共可以設(shè)置的航線數(shù)>0則} begin d[i,3]:=L+1; {本城市可以設(shè)置的航線數(shù)在下個(gè)城市可以設(shè)置航線數(shù)的基礎(chǔ)上加1} d[i,4]:=p {D[I,4]等于本城市后續(xù)城市的代碼} end end; k:=d[1,3]; {K為可以設(shè)置最大航線數(shù),假設(shè)初值為第一個(gè)城市可以設(shè)置的航線數(shù)} L:=1; {L為城市代碼,初值為第一個(gè)城市} for i:=2 to n do {找出可以設(shè)置航線的最大值,賦值給K,同時(shí)L記下哪個(gè)可以設(shè)置最大航線數(shù)的城市代碼} if d[i,3]>k then begin k:=d[i,3]; L:=i end; for i:=1 to n do {打印結(jié)果,因?yàn)橛锌赡苡卸喾N方案,所以只要哪個(gè)城市可以設(shè)置的航線數(shù)等于最大值K就打印結(jié)果} if d[i,3]=k then print(i) end. 八、最長(zhǎng)不降子序列 (1)問(wèn)題描述 設(shè)有由n個(gè)不相同的整數(shù)組成的數(shù)列,記為: a(1)、a(2)、……、a(n)且a(i)<>a(j) (i<>j) 例如3,18,7,14,10,12,23,41,16,24。 若存在i1- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來(lái)的問(wèn)題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請(qǐng)點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
9.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁(yè)顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開(kāi)word文檔。
- 特殊限制:
部分文檔作品中含有的國(guó)旗、國(guó)徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 2019-2020年高中信息技術(shù) 全國(guó)青少年奧林匹克聯(lián)賽教案 動(dòng)態(tài)規(guī)劃實(shí)例分析及程序?qū)崿F(xiàn) 2019 2020 年高 信息技術(shù) 全國(guó)青少年 奧林匹克 聯(lián)賽 教案 動(dòng)態(tài) 規(guī)劃 實(shí)例 分析 程序 實(shí)現(xiàn)
鏈接地址:http://m.appdesigncorp.com/p-2577035.html