【2018.2.26算法總結#分治】
阿新 • • 發佈:2018-02-27
輸出格式 play light 註意 等待 gpo 如同 lose sin
每天早上,租鞋窗口都會排起長龍,假設有還鞋的m個,有需要租鞋的n個。現在的問題是,這些人有多少種排法,可以避免出現體育組沒有冰鞋可租的尷尬場面。(兩個同樣需求的人(比如都是租鞋或都是還鞋)交換位置是同一種排法)
輸入格式
兩個整數,表示m和n
輸出格式
一個整數,表示隊伍的排法的方案數。
樣例輸入
3 2
樣例輸出
5
數據規模和約定
m,n∈[0,18]
分治法:1.將一個問題分成許多小問題,求解小問題。2.將小問題重新組合成一個問題。
例子:
-
排隊購票
問題描述:一場球賽開始前,售票工作正在緊張進行中。每張球票為50元,有m+n個人排隊等待購票,其中有m 個人手持50元的鈔票,另外n個人手持100元的鈔票。求出這m+n個人排隊購票,使售票處不至出現找不開錢的局面的不同排隊種數 。(約定:開始售票時售票處沒有零錢,拿同樣面值鈔票的人對換位置為同一種排隊。)
問題分析:
令f(m,n)表示有m個人手持50元的鈔票,n個人手持100元的鈔票時共有的排除總數。 分以下3種情況來討論。
- n=0:意味著排隊購票的所有人手中拿的都是50元的錢幣,註意到拿同樣面值鈔票的人對換位置為同一種排隊,那麽這m個人的排隊總數為1,即f(m,0)=1。
- m<n:當m<n時,即購票的人中持50元的人數小於持100元的鈔票,即使把m張50元的鈔票都找出去,仍會出現找不開錢的局面,這時排隊總數為0,即f(m,n)=0。
- 其它情況 第m+n個人手持100元的鈔票,則在他之前的m+n-1個人中有m個人手持50元的鈔票,有n-1個人手持100元的鈔票,此種情況共有f(m,n-1)。 第m+n個人手持50元的鈔票,則在他之前的m+n-1個人中有m-1個人手持50元的鈔票,有n個人手持100元的鈔票,此種情況共有f(m-1,n)。
由加法原理得到f(m,n)的遞歸關系: f(m,n)=f(m,n-1)+f(m-1,n)
初始條件: 當m<n時,f(m,n)=0 當n=0時,f(m,n)=1
long f(int j,int i) { long y; if(i==0) y=1; else if(j<i) y=0; // 確定初始條件 else y=f(j-1,i)+f(j,i-1); // 實施遞歸 return(y); }
2.未名湖邊的煩惱
問題描述
每年冬天,北大未名湖上都是滑冰的好地方。北大體育組準備了許多冰鞋,可是人太多了,每天下午收工後,常常一雙冰鞋都不剩。每天早上,租鞋窗口都會排起長龍,假設有還鞋的m個,有需要租鞋的n個。現在的問題是,這些人有多少種排法,可以避免出現體育組沒有冰鞋可租的尷尬場面。(兩個同樣需求的人(比如都是租鞋或都是還鞋)交換位置是同一種排法)
分析:如同第一個例子一樣,先考慮最初始兩種條件,再考慮最後一個人的情況。
1 #include<iostream> 2 #include<stdio.h> 3 using namespace std; 4 int f(int m,int n){ 5 int y; 6 if(n==0)//沒有人借鞋子 7 y=1; 8 else if(m<n)//借鞋子的人多 9 y=0; 10 else 11 y=f(m-1,n)+f(m,n-1);//最後一個人之前有多少個人可以退鞋 12 return y; 13 } 14 int main(){ 15 int m,n; 16 cin>>m; 17 cin>>n; 18 cout<<f(m,n)<<endl; 19 20 return 0; 21 }View Code
【2018.2.26算法總結#分治】