目錄b. 【例題2】奇怪漢諾塔
c. 【例題3】數的劃分
d. 【例題4】傳球遊戲
e. 【例題5】平鋪方案
「基礎演算法」第1章 遞推演算法課堂過關
求多少個n個數的排列a,滿足對於任意的\(i (1\leq i \leq n) a_i \neq i\),輸入n,輸出乙個整數,表示答案
設\(f(n)\)表示n個數的合法方案排列個數
考慮第x個元素,把他放到k位置上,一共有 n-1種放法
考慮第k個元素,共兩種可能:
把k放在位置n,則對於除k,n以外的其他元素,錯排即可,共\(f(n-2)\)種方案
不把k放在位置n,則對於n-1個元素的錯排,有\(f(n-1)\)種方法
故,有遞推式:
\[f(x)=
\left\
(n-1)\cdot (f(x - 1) + f(x - 2)) \quad\ \ (x\geq3)\\
1\qquad\qquad\qquad\qquad\qquad\qquad\qquad(x=1)\\
2\qquad\qquad\qquad\qquad\qquad\qquad\qquad(x=2)
\end\right.
\]
#include #include #define int long long
using namespace std;
int n;
int ans;
int f(int x)
signed main() /*0
131256
3212175
17008
150504
1485465
*/
有a、b、c、d四座塔, 給定n個圓盤,一開始全部放在a塔,直接輸出n=1~12時的所有答案,無輸入
具體規則同普通漢諾塔
回顧三座塔的情況:
將a塔的n-1個圓盤移至b塔,最後乙個圓盤直接移至c塔,再將b塔的所有圓盤移到c塔
有遞推式:
\[d(x)=
\left\
&1+2\cdot d(x - 1) \qquad(x\geq2)\\
&1\qquad\qquad\qquad\qquad(x=1)
\end\right.
\]當漢若塔數量為4座時:
考慮將a塔的j個盤子轉移到b塔(移動步數為\(f(j)\)),然後不對b塔進行操作,將剩下n-j個盤子轉移到d塔,移動步數為\(d(n-j)\),最後將b塔的j個盤子轉移到d塔,移動步數為\(f(j)\),我們直接列舉j,取最小值即可
遞推式:
\[f(x)=
\left\
&\min \} \qquad(x\geq2,j\in[0,x])\\
&1\qquad\qquad\qquad\qquad\qquad\qquad\ (x=1)
\end\right.
\]
#include #include #define min_(_ , __) (_ < __ ? _ : __)
using namespace std;
int d[20] , f[20];
int main()
for(int i = 1 ; i <= 12 ; i++)
cout << f[i] << endl;
return 0;
}/*答案13
591317
2533
4149
6581
*/
將整數n分成k份,每份不為空,求不同的劃分方案數(數字相同而順序不同的兩個方案視為相同的方案)
例如:下面三種分法被認為是相同的:
1,1,5; 1,5,1; 1,1,5.
設$ f(n,k)$表示將整數n分成k份的不重複方案數
當\(n>k\)時:
k份中至少有乙份為「1」:方案數為\(f(n-1,k-1)\)
k份中沒有乙份為「1」 :方案數為\(f(n-k,k)\)(在n-k被分成k份的基礎上,每乙份都加上「1」)
故有遞推式:
\[f(n,k)=
\left\
&f(n-1,k-1)+f(i-k,k) \qquad\ \ \ (x>k)\\
&1\qquad\qquad\qquad\qquad\qquad\qquad\qquad(n=k)\\
&0\qquad\qquad\qquad\qquad\qquad\qquad\qquad(n
#include #include using namespace std;
int n , k;
int f[1010][1010];
int main()
cout << f[n][k];
return 0;
}
傳送門
設\(f(i , j)\) 表示經過j次傳球後,球落在第i個同學手中的方案數(說明一下,我**裡面把遊戲剛開始,球在小蠻手上的情況當做第1次傳球,故有一丟丟不一樣)
很顯然,有:
\[f(i,j)=f(i-1,j-1)+f(i+1,j-1)
\]其中,根據題目「n 個同學站成乙個圓圈」的背景,「i+1」 、"i-1"均應該在\([1,n]\)範圍內,越界自行處理
想出並寫出演算法10min,寫出高精度40min
設\(f(x)\)表示鋪成2*x的矩形的方案數
顯然\(f(1)=1,f(2)=3\)
對於其他情況,我們考慮:
將1*2的矩形豎著拼到2*(n-1)的矩形上,方案數為f(x-1)
將兩個1*2的矩形橫著拼到2*(n-2)的矩形上,方案數為f(x-2)
將乙個2*2的矩形橫著拼到2*(n-2)的矩形上,方案數為f(x-2)
故遞推式:
\[f(x)=
\left\
&2\cdot f(x - 2) + f(x - 1) \quad(x\geq3)\\
&1\qquad\qquad\qquad\qquad\qquad(x=1)\\
&3\qquad\qquad\qquad\qquad\qquad(x=2)
\end\right.
\]最後,看樣例都知道要高精度
#include #include #include #define ll long long
using namespace std;
#define m 1010
struct bignum
void print()
bignum operator + (const bignum &b) const
++ans.siz;
if(ans.a[ans.siz - 1] == 0)--ans.siz;
return ans;
}};bignum f[1010];
int main()
return 0;
}
Num 1 遞推演算法
getchar getchar 沒有引數,返回來自輸入裝置的下乙個字元。停住介面觀察結果 return 0 a上4年大學,假設銀行的年利率為0.018,a每月從銀行卡中取出1000元作為生活費,那麼求解最開始存入銀行卡的錢為多少?求解過程 若在第48個月a畢業時來本帶息取出100元,則要先求出第47...
第二章 遞推演算法
乙個問題的求解需一系列的計算,在已知條件和所求問題之間總存在著某種相互聯絡的關係,在計算時,如果可以找到前後過程之間的數量關係 即遞推式 那麼,從問題出發逐步推到已知條件,此種方法叫逆推。無論順推還是逆推,其關鍵是要找到遞推式。這種處理問題的方法能使複雜運算化為若干步重複的簡單運算,充分發揮出計算機...
第一章 遞推演算法
特點 乙個問題的求解需一系列的計算,在已知條件和所求問題之間總存在著某種相互聯絡的關係,如果可以找到前後過程之間的數量關係 即遞推式 那麼,從問題出發逐步推到已知條件,此種方法叫逆推。無論順推還是逆推,其關鍵是要找到遞推式。猴子吃桃 遞推關係 f n f n 1 2 1 f n 1 f n 1 2 ...