1. 程式人生 > >【2018.2.26算法總結#分治】

【2018.2.26算法總結#分治】

輸出格式 play light 註意 等待 gpo 如同 lose sin

分治法:1.將一個問題分成許多小問題,求解小問題。2.將小問題重新組合成一個問題。

例子:

  1. 排隊購票

問題描述:一場球賽開始前,售票工作正在緊張進行中。每張球票為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個。現在的問題是,這些人有多少種排法,可以避免出現體育組沒有冰鞋可租的尷尬場面。(兩個同樣需求的人(比如都是租鞋或都是還鞋)交換位置是同一種排法)
輸入格式   兩個整數,表示m和n 輸出格式   一個整數,表示隊伍的排法的方案數。 樣例輸入 3 2 樣例輸出 5 數據規模和約定   m,n∈[0,18]

分析:如同第一個例子一樣,先考慮最初始兩種條件,再考慮最後一個人的情況。

技術分享圖片
 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算法總結#分治】