動態規劃系列專題講義
專題一:斐波那契數列
name: 動態規劃專題之斐波那契數列
author:
date: 22-03-17 08:56
description: 1755_菲波那契數列
描述:斐波那契數列是指這樣的數列: 數列的第乙個和第二個數都為1,接下來每個數都等於前面2個數之和。給出乙個正整數a,要求斐波那契數列中第a個數是多少。
輸入:第1行是測試資料的組數n,後面跟著n行輸入。每組測試資料佔1行,包括乙個正整數a(1<= a <= 20)
輸出:輸出有n行,每行輸出對應乙個輸入。輸出應是乙個正整數,為菲波那契數列中第a個數的大小
樣例輸入
樣例輸出
1 #include
#include
using namespace std;
const int maxn = 50;
int f1[maxn];//fibonacci數列
int f2[maxn] = ;//fibonacci數列
int fibonacci(int n); //遞迴演算法
int fibonacci_1(int n); //備忘錄:自頂而下
int fibonacci_2(int n);//動態規劃:自底而上
int fibonacci_3(int n);//動態規劃:降維優化
int main()
int n, a;
fibonacci_2(maxn);//動態規劃,先記錄所有子問題的解
cin>> n;
for(int i=0; icin>> a;
cout << fibonacci(a) << endl;
cout << fibonacci_1(a) << endl;
cout << f2[a] << endl;
cout << fibonacci_3(a) 演算法1:遞迴演算法,沒有記錄任何中間結果。
int fibonacci(int n)
if (n == 0 || n == 1) //遞迴出口
return //語句1
return fibonacci( ) + fibonacci( ); //語句2
問題1:將語句1和語句2補充完整。
問題1:語句1:return n;
語句2:return fibonacci(n-1) +fibonacci(n-2);
演算法2:備忘錄演算法:自頂而下,需要用到全域性變數f1 [maxn]。
int fibonacci_1(int n)
if (f1[n] > 0) //如果這個問題曾經計算過,直接返回
return //語句1
if(n == 0 || n == 1) //遞迴出口
f1[n] = //語句2
else
f1[n]= //語句3
return f1[n];
問題1:將語句1,語句2和語句3補充完整。
問題2:與演算法1(遞迴演算法)相比,演算法2(備忘錄演算法)有哪些優越之處?
問題1:語句1:return f1[n];
語句2:f1[n] = n;
語句3:f1[n] = fibonacci_1(n-1) + fibonacci_1(n-2);
問題2:遞迴演算法進行了重複計算,而備忘錄演算法利用一維陣列f1[n]記錄了子問題的解,無需重複計算,大大提高了效率。
演算法3:動態規劃:自底而上,需要用到全域性變數int f2[maxn] =;。
int fibonacci_2(int n)
for (int i=2; i<=n; i++)
f2[i] = //語句1
return f2[n];
問題1:將語句1補充完整。
問題2:與演算法2(備忘錄演算法)相比,演算法3(動態規劃)有哪些異同?
問題1:語句1:f2[i] = f2[i-1] + f2[i-2];
問題2:備忘錄和動態規劃演算法都是利用遞推表示式獲得子問題的解,並記錄了子問題的解,用空間換時間,提高了時間效率。但是二者的思考方向不同,備忘錄演算法是自頂而下,從最終解出發,採用遞迴的方式來求解;動態規劃演算法是自底而上,從最小的子問題出發,逐步向上求出較大問題的解,直到獲得最終解。
演算法4:/動態規劃:降維優化,使用3個變數代替一維陣列。
int fibonacci_3(int n)
intcur, pre1, pre2;
pre1= 0, cur = pre2 = 1; //初始化
for (int i=2; i<=n; i++) //自底向上,迭代更新變數值
cur= //語句1
pre1 = //語句2
pre2 = //語句3
return cur;
問題1:將語句1,語句2和語句3補充完整。
問題2:與演算法3(基本動態規劃演算法)相比,演算法4(動態規劃降維優化)有哪些異同?
問題1:語句1:cur = pre1 + pre2;
語句2:pre1 = pre2;
語句3:pre2 = cur;
問題2:二者同屬動態規劃演算法,都利用額外的變數(或陣列)記錄了各個子問題的解,都是從最小的子問題出發,逐步向上求出較大問題的解,直到獲得最終解。演算法3保留了所有子問題的解,雖然需要較多的空間,但是一次計算之後,就可以直接輸出任意解了;演算法4利用斐波那契數列遞推公式的特性,只保留了每個元素的當前值和它前面的2個元素值,對計算過程中產生的子問題解用過即棄,所需空間較少,但每次求解新元素的值,都需要從頭開始計算,適用於只需要求某乙個元素值的情形。
課後練習:
練習1:1788_pell數列
描述:pell數列a1, a2, a3, ...的定義是這樣的,a1 = 1, a2 = 2, ... , an = 2* an-1 + an - 2 (n > 2)。
給出乙個正整數k,要求pell數列的第k項模上32767是多少。
輸入:第1行是測試資料的組數n,後面跟著n行輸入。每組測試資料佔1行,包括乙個正整數k (1 ≤ k < 1000000)。
輸出:n行,每行輸出對應乙個輸入。輸出應是乙個非負整數。
樣例輸入
樣例輸出
練習2:3089_爬樓梯
描述:樹老師爬樓梯,他可以每次走1級或者2級,輸入樓梯的級數,求不同的走法數。
例如:樓梯一共有3級,他可以每次都走一級,或者第一次走一級,第二次走兩級也可以第一次走兩級,第二次走一級,一共3種方法。
輸入:輸入包含若干行,每行包含乙個正整數n,代表樓梯級數,1<= n <= 30
輸出:不同的走法數,每一行輸入對應一行輸出
樣例輸入
樣例輸出
練習3:2046_骨牌鋪方格
描述:在2×n的乙個長方形方格中,用乙個1× 2的骨牌鋪滿方格,輸入n ,輸出鋪放方案的總數。例如n=3時,為2× 3方格,骨牌的鋪放方案有三種,如下圖:
輸入:輸入資料由多行組成,每行包含乙個整數n,表示該測試例項的長方形方格的規格是2×n(0輸出:對於每個測試例項,請輸出鋪放方案的總數,每個例項的輸出佔一行。
樣例輸入13
2樣例輸出13
2練習4:2718_移動路線
描述:桌子上有乙個m行n列的方格矩陣,將每個方格用座標表示,行座標從下到上依次遞增,列座標從左至右依次遞增,左下角方格的座標為(1,1),則右上角方格的座標為(m,n)。
小明是個調皮的孩子,一天他捉來乙隻螞蟻,不小心把螞蟻的右腳弄傷了,於是螞蟻只能向上或向右移動。小明把這只螞蟻放在左下角的方格中,螞蟻從左下角的方格中移動到右上角的方格中,每步移動乙個方格。螞蟻始終在方格矩陣內移動,請計算出不同的移動路線的數目。
對於1行1列的方格矩陣,螞蟻原地移動,移動路線數為1;對於1行2列(或2行1列)的方格矩陣,螞蟻只需一次向右(或向上)移動,移動路線數也為1……對於乙個2行3列的方格矩陣,如下圖所示:
|(2,1)|(2,2)|(2,3)|
|(1,1)|(1,2)|(1,3)|
螞蟻共有3種移動路線:
路線1:(1,1) → (1,2) → (1,3) → (2,3)
路線2:(1,1) → (1,2) → (2,2) → (2,3)
路線3:(1,1) → (2,1) → (2,2) → (2,3)
輸入輸入只有一行,包括兩個整數m和n(0輸出
輸出只有一行,為不同的移動路線的數目。
樣例輸入
2 3樣例輸出
pan � f)=np��ج → (1,2) → (2,2) → (2,3)
路線3:(1,1) → (2,1) → (2,2) → (2,3)
輸入輸入只有一行,包括兩個整數m和n(0輸出
輸出只有一行,為不同的移動路線的數目。
樣例輸入
2 3樣例輸出
動態規劃之斐波那契數
70.爬樓梯 e 假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?注意 給定 n 是乙個正整數。第n階台階的路線等於n 1階的路線數加上n 2階的路線數,第一階的路線數為1,第二階路線數等於2,遍歷求和即可 class soluti...
動態規劃 斐波那契數列
問 大家都知道斐波那契數列,現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項 從0開始,第0項為0 n 39 斐波那契數列簡單介紹 我的解法 注 從fibonacci n 1 fibonacci n 2 明顯看出使用的是遞迴,此題用遞迴兩三行 即可搞定。但是,若出題者準備著乙個超大的n,那麼很有...
斐波那契系列
91.解碼方法 一條包含字母a z的訊息通過以下方式進行了編碼 a 1 b 2 z 26給定乙個只包含數字的非空字串,請計算解碼方法的總數。示例 1 輸入 12 輸出 2 解釋 它可以解碼為 ab 1 2 或者 l 12 示例 2 輸入 226 輸出 3 解釋 它可以解碼為 bz 2 26 vf 2...