【动态规划】买票找零

水题一道,但是感觉起来挺有意思的。

一场激烈足球赛即将开始,售票员紧张地卖票着……。

每张球票50元,现在有2n1<=n<=18)个球迷排队购票,其中n个手持50元钞票,另外n个手持100元钞票。假设开始售票时售票处没有零钱可以找零。

问这2n个人有多少种排队方式,不至使售票处出现找不出零的局面?

例如当n=3时,共6人,3人持50元,3人持100元。可以找零的排队方式有如下5种:

50 50 50 100 100 100

50 50 100 100 50 100

50 50 100 50 100 100

50 100 50 50 100 100

50 100 50 100 50 100

 

输入格式

输入:

输入n,表示2n个球迷,其中n个手持50元,另外n个手持100元。

 

输出格式

输出:

2n个人,可以找零的排队方式数。

 

输入样例

3

 

输出样例

5

 

分析:

一开始天真地以为可以直接用高中的排列组合公式算(想想发现忘光了T_T),后来算了下才发觉不对劲。后面换了种想法。

Q1:假设抽屉里面没有钱,那么只能将一个50的排第一位。

Q2:假设抽屉有50元钱,那么这次可以随意排50或者100的在第一位。

问题可以抽象成,假设抽屉有money 的钱,有n1个人拿着50元,n2个人拿着100元待排队,求排队的方式数。开始是 money == 0, n1 == n2 == n

很好的一个递归模型了,自顶向下,采用备忘录方法优化。

函数定义:

int GetCount(int n1, int n2, int  money);

 

对于Q1

count = GetCount(n1 - 1, n2, money + 50) ;

即抽屉没钱,只能先排一个50的在前面

 

对于Q2: 

count = GetCount(n1 - 1, n2, money + 50) + GetCount(n1, n2-1, money-50);

即抽屉有钱的话,排序总数量是两种子问题的总和。

 

 

然后讨论问题的递归出口。

由上面分析可以看出,最终出口肯定是 n1 不断减少,直到0, money不断增加,增加到跟n2相等的情况。这种时候相当于,抽屉有 50元,刚好有 个人拿着100元过来买票。那么很好理解,只有一种排队方法。

 

代码就不贴了。从来认为算法的代码没有可读性可言,看代码不如看分析。

你可能感兴趣的:(C/C++,解题代码)