漂亮列印問題與動規模型的建立

2021-06-26 18:28:39 字數 1592 閱讀 4074

**

這是演算法導論動態規劃一章的課後思考題

題目如下:

由給定的n個英文單詞組成一篇文章,每個單詞的長度(字元個數)依次為l1,l2...要在一台印表機上將這段文章漂亮的列印出來.印表機每行最多可列印m個字元.這裡說說的漂亮定義如下:在印表機所列印的每一行中,行首和行尾可不留空格;行中每兩個單詞之間可留乙個空格;如果在一行中列印從單詞i到單詞j的字元,則按照列印規則,應該在一行中列印sum(li,i<=i比如m=5

a︻bc︻

d︻ef︻

g(最後一行不算)

︻表示空格  總空餘為1*1*1+1*1*1=2

最近一直在研究動規方面的問題,看到這道題後略一思索便想出了該問題的最優子結構:最後一行必定是從i到n,當然i必須在能夠列印的範圍內。i定下來之後,前面的段落必定是最小和,否則必定能找到乙個更優解。這樣不斷迭代到初始情況,便可解決問題。

(1)狀態變數如何表示??一維?二維??

(2)邊界情況如何處理。

一、最後一行不算,應該如何處理?

二、每一行是否超出最大字元數如何判斷?

三、初始狀態怎麼處理?

先來看狀態變數。剛一開始可能會想到用二維dp。但仔細想過後發現無法實現。於是轉向一維,我們以陣列c[j]表示以第j個元素結尾的段落,且第j+1個另起一行。這樣便寫出了狀態轉移方程c[j]=max (1<=i<=j),其中lc(i,j)表示以i起頭,以j結尾的一行。這樣便刻畫出了我們一開始想到的最優子結構!

接下來是邊界處理。我們假設資料下標從1開始。那麼可取c[0]=0,如果取c[0]作為次狀態,那麼表示當前狀態處在第一行。比如,c[1]=c[0]+lc(1,1)=l1。然後我本來準備進行判斷,如果i到j超過規定字元,則i++。然後如果j=n,並且i到j在規定字元內,c[j]=max;

(1<=i<=j)。那麼狀態轉移就變成了

(1)max (1<=i<=j&&lc(i,j)<=m)    //正常情況

c[j]= (2)c[i-1]                         (j=n&&1<=i<=j&&lc(i,j)<=m)            //最後一行

這樣實現起來要加上許多判斷,就顯得很繁瑣。

導論上的方法是,令lc()的返回值有三種狀態:正常,0,無窮。這樣只需乙個狀態轉移c[j]=max (1<=i<=j),並且自動過濾掉了邊界情況,漂亮!

至此問題已全部解決,可以開始寫**了。從這個例子可以看出,dp的邊界情況處理是非常重要的。我們的解題順序大致是:刻畫最優子結構à刻畫狀態變數à考慮邊界情況à寫**。本人也是初學dp不久,只是寫一寫自己的思考,歡迎高手指正j

源**:

#includeusing namespace std;

int m,n; //每行最大容量

int c[1000]; //狀態陣列

int l[1000];

int p[1000]; //儲存記錄用於重構最優解的陣列

//lc函式用來分類,把邊界情況考慮進去,好想法!!!

int lc(int i,int j)

void prettypainting()

漂亮列印問題與動規模型的建立

這是演算法導論動態規劃一章的課後思考題 題目如下 由給定的 n個英文單詞組成一篇文章,每個單詞的長度 字元個數 依次為 l1,l2.要在一台印表機上將這段文章漂亮的列印出來 印表機每行最多可列印 個字元 這裡說說的漂亮定義如下 在印表機所列印的每一行中,行首和行尾可不留空格 行中每兩個單詞之間可留乙...

動規之遊艇租用問題

問題描述 長江俱樂部在長江設定了n個遊艇出租站1,2,n,遊客可在這些遊艇出租站租用遊艇,並在下游的任何乙個遊艇出租站歸還遊艇。遊艇出租站i到遊艇出租站j之間的租金為r i,j 設計乙個演算法,計算出從出租站1到出租站n所需要的最少租金。樣例輸入 35 15 7樣例輸出 12分析 fin i j 表...

矩陣連乘問題 區間動規

解答想法 共兩行第一行n 1 n 100 代表矩陣個數。第二行有n 1個數,分別為q 0 q 1 q n 1 q k 2000 代表第 k 個矩陣是q k 1 xq k 維的。共兩行第一行 m,為最優代價。注 測試用例中 m 值保證小於 2 31 第二行為最優順序。如 a1 a2a3 a4 最外層也...