一,問題描述
假設有個機械人坐在 x×y 網格的最左上角,每次只能向下或者向左移動。最左上角的座標標記為(0,0),最右下角的座標為(x,y)
請問:機械人從(0,0)走到(x,y)共有多少種走法?其實這個問題與 這篇文章 中提到的問題非常相似。
二,問題分析
這個問題一共有三種方式來求解。第一種是使用公式;第二種是使用遞迴;第三種是使用動態規劃
使用遞迴和動態規劃,其實本質上是一致的。都是使用組合原理進行問題分析。
機械人從(0,0)走到(x,y)一共需要走 x+y步。其中必須有x步是向下走的(因為最終的橫座標是x)。問題轉化為:從x+y步走法中,選出x步是向下走,一共有多少種選法?這是乙個組合問題了。答案是c(x+y,x)
還有另一種理解方式:
由於機械人不能往回走,只能向下或者向左走。因此,將向下走記為 down,向左走記為left。問題就轉化為的乙個全排列問題。
即:集合有兩個元素,down和left。down一共有x個,left一共有y個。
從(0,0)走到(x,y)就相當於對集合所有的元素進行全排列。由於這是乙個「重集合」,故全排列數為 (x+y)!/x!·y!
其中,(x+y)!/x!·y! 等於 c(x+y,x)
對於(x,y),一共有兩種情況:從(x-1,y)向下走一步到達(x,y);從(x,y-1)向右走一步到達(x,y)
設steps(x,y)表示從(0,0)走到(x,y)一共用的方式數,那麼steps(x,y)=steps(x-1,y)+steps(x,y-1)
初始條件:steps(0,0)=1;steps(x,0)=steps(0,y)=1
因此,就可以代表上面的公式使用遞迴或者dp求解了。
三,**實現
publicclass
steps
//使用遞迴來求解
private
static
int steps_recur(int x, int
y)
//dp resolve
public
static
int steps_dp(int x, int
y)
}return
dp[x][y];
}//使用公式來求解
public
static
int steps_factorial(int x, int
y)
//求n!
public
static
int factorial(int
n)
//test
public
static
void
main(string args)
}
四,參考資料
動態規劃之fib數列類問題應用
排列與組合的一些定理(二)
排列與組合的一些定理
動態規劃之硬幣組合問題
問題 如果我們有面值為1元 3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元?動態規劃的本質是將原問題分解為同性質的若干相同子結構,在求解最優值的過程中將子結構的最優值記錄到乙個表中以避免有時會有大量的重複計算。例如硬幣組合問題,若求湊夠11元的最少硬幣數,可以先從湊夠0元 1元 2元 的子結構開...
動態規劃問題之求組合數
我們知道,組合數在組合數學中非常有用,組合數是乙個十分常用的數字。比如,書架上有4本書abcd,我們想拿2本讀,那麼有c 4,2 種方法。這個數字的求法是 4!2!4 2 其中n!1 2 3.n,是階乘數。所以按定義求其實也十分 容易 這裡是指容易寫罷了。先求乙個階乘 def fac n if n ...
動態規劃之自由組合問題
1.有一定的錢,去買一些東西,求最多有多少買種東西的方案?2.如果一種物品最多能買一次,則是01揹包變形型別 3.如果乙個物品能多次購買,則是完全揹包變形型別 4.每一種買東西的方案必須要把錢剛好花完。1.神奇的口袋 2.買書 第一道題裡 錢 是固定的,輸入 東西的 第二道題裡 東西的 是固定的,輸...