【2018.2.26算法总结#分治】

分治法: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

 

posted @ 2018-02-26 21:04  一头  阅读(281)  评论(0编辑  收藏  举报