前端學習算法1 :老虎和羊,吃不吃問題(動態規劃入門)

撇開什麼是動態規劃不談,咱們先來看看題幹:優化

有500只老虎,1只羊,一片草原。老虎和羊,均可以吃草活着,對,這個題中的老虎能夠吃草。老虎呢,也能吃羊,不容許不少只老虎一塊兒吃羊,只容許一隻老虎吃一隻羊,而且,吃完羊以後,這個老虎就會變成羊。那麼問,老虎會不會吃羊? 提示:老虎很聰明,每隻老虎都很聰明。spa

小A回答

不吃啊,我堂堂威風老虎,幹嗎要變成羊?而且變成羊以後,就該被欺負了3d

老師說

你坐下code

小B回答

吃,由於羊肉好吃cdn

老師說

你坐下blog

小C回答

不吃,羊那麼可愛,吃了幹嗎,不吃還能多個小夥伴遊戲

小M回答

不吃! 要保護生態平衡!數學

老師說

這題我能不能撤回?it

不開玩笑了,答案在下面揭曉,爲了避免使得一打開頁面就看到答案,我加些空格。io

10

9

8

7

6

5

4

3

2

1

公佈答案:不吃。爲何呢?由於老虎很聰明啊。WTF,這是什麼理由?不急不急,看看下面的解釋,(先插播一個廣告,就是本人很是喜歡的遊戲‘逆轉裁判’,文字遊戲,結局一般是大逆轉,太贊。)

無從下手之際,不妨逆轉一下思惟,直接想500這個數字,怎麼也不具備什麼表明性,要是能聯想起大學時候的數學概括法,就好辦多了。數學概括法一般用來證實一些看起來就不用證實的東西,無從下手的時候,就找特殊狀況,好比無窮小的時候知足,無窮大的時候知足,而後再證實個有表明性的通常特例知足就行了。

那麼咱們也從特殊狀況入手

  1. 如今只有 1 老虎,1 羊,那麼這隻羊會被吃嗎?

確定被吃了,老虎吃了羊後,變成羊,也不會有生命危險了。老虎很聰明,幹嗎不吃。

  1. 如今只有 2 老虎,1 羊,那麼這隻羊會被吃嗎?

不會吃。這兩隻老虎都很聰明,吃了後本身變成了羊,就會被另外一隻老虎吃掉本身。

  1. 如今只有 3 老虎,1 羊,那麼這隻羊會被吃嗎?

吃啊,吃! 反正吃完後,變成上面的狀況後沒有老虎敢吃我了,我得體驗體驗羊肉。

  1. 如今只有 4 老虎,1 羊,那麼這隻羊會被吃嗎?

不吃,吃了後變成上面狀況後,本身變成了羊,該被吃掉了。

  1. 如今只有 5 老虎,1 羊,那麼這隻羊會被吃嗎?

吃啊,吃! 反正吃完後,變成上面的狀況後沒有老虎敢吃我了,我得體驗體驗羊肉。

  1. 如今只有 6 老虎,1 羊,那麼這隻羊會被吃嗎?

不吃,吃了後變成上面狀況後,本身變成了羊,該被吃掉了。

那麼由以上的狀況推導一下,是否是規律已經出來了? 前提不是說了嗎,每一個老虎都很聰明,500是什麼數?是偶數,那麼是不會吃的。

動態規劃 Dynamic Programming

動態規劃意思就是說,大事化小,小事化了。術語的話,包含三個,最優子結構邊界狀態轉移公式,舉一個最簡單的例子,能更好的理解這三個術語

樓梯臺階有12階,一步只能走1階或者2階,那麼,請問走完樓梯有多少走法?

  1. 走到最後一個臺階的前一個狀況,只能有兩種吧,就是從第11臺階走一步上來,或者從10臺階走兩步上來,那麼無論有多少走法走到了11階假設是X種走法吧,假設是Y種走法走到了10階,那麼,走到12階的走法必定是X+Y,這個是成立的吧。這就是最優子結構
  2. 那什麼是邊界呢?本例子中,走到第一個臺階,就一種走法吧,沒有臺階,那就0種走法吧,走到第二個臺階,也就2種走法,其實這就是邊界了。
  3. 那麼狀態轉移公式就水到渠成了,F(n) = F(n-1) + F(n-2)

別說話,看代碼

function fun(n) {
  if (n < 0){
	return 0
  }
  if (n === 1){
	return 1
  }
  if (n === 2){
	return 2
  }
  return fun(n-1) + fun(n-2)
}
console.log('12臺階的走法 :' + fun(12) )
console.log('11臺階的走法 :' + fun(11) )
console.log('10臺階的走法 :' + fun(10) )
console.log('9臺階的走法 :' + fun(9) )
console.log('8臺階的走法 :' + fun(8) )
console.log('7臺階的走法 :' + fun(7) )
console.log('6臺階的走法 :' + fun(6) )
console.log('5臺階的走法 :' + fun(5) )
console.log('4臺階的走法 :' + fun(4) )
console.log('3臺階的走法 :' + fun(3) )
console.log('2臺階的走法 :' + fun(2) )
console.log('1臺階的走法 :' + fun(1) )
複製代碼

運行結果以下

其實上面代碼是存在問題的,有不少重複的計算。不妨把n限定小一些來看 f(4) = f(3) + f(2),而f(3) = f(2) + f(1),f(2)就是重複計算了。那麼代碼如何進行優化一翻?

看到上面打印的結果,其實也能發現出規律來,就是3的結果,只依賴1和2,那4的結果有隻依賴2和3,而1,2的結果又是顯而易見的,那麼咱們能否逆轉一下思惟,從下而上計算呢?因而代碼以下改造,也就是真正的動態規劃實現

function fun(n) {
  if (n < 0){
	return 0
  }
  if (n === 1){
	return 1
  }
  if (n === 2){
	return 2
  }
  var a = 1
  var b = 2
  var temp = 0
  for(var i = 3; i <= n; i++){
	temp = a + b
	a=b
	b=temp
  }
  return temp
}
console.log( '優化版' )
console.log('12臺階的走法 :' + fun(12) )
console.log('11臺階的走法 :' + fun(11) )
console.log('10臺階的走法 :' + fun(10) )
console.log('9臺階的走法 :' + fun(9) )
console.log('8臺階的走法 :' + fun(8) )
console.log('7臺階的走法 :' + fun(7) )
console.log('6臺階的走法 :' + fun(6) )
console.log('5臺階的走法 :' + fun(5) )
console.log('4臺階的走法 :' + fun(4) )
console.log('3臺階的走法 :' + fun(3) )
console.log('2臺階的走法 :' + fun(2) )
console.log('1臺階的走法 :' + fun(1) )
複製代碼

運行結果和以前的相同,以下

(其實這也只是動態規劃入門,後續會有進階題目。其實也沒啥人看,只是寫給本身記錄一下而已)

相關文章
相關標籤/搜索