算法实战学习之递归(1)

来源:互联网 发布:最游记一键淘宝端 编辑:程序博客网 时间:2024/04/30 13:59

又有好久没写博客了,主要是上个星期五刚考完试,星期六星期天有没有咋学习,就好好放松了一下,今天都星期一了呀,再不发篇博文,我都不好意思了啊。下个星期会有校赛,所以最近就会把比较常见的算法过一遍,递归是第一篇,而且还会有后续,反正大家敬请期待哦!

言归正传,回到今天的主题——递归算法。

说实在话,递归是属于不是很好理解的一类算法,毕竟它是利用了计算机的重复性工作,计算思维在人看来确实不好理解,我们人类不会那么机械地去解决一个问题。说到这里,我感觉很多人将递归和迭代给弄混了,这里我有必要帮助大家区分一下。

递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己.

一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.递归的能力在于用有限的语句来定义对象的无限集合.

使用递归要注意的有两点:

1)递归就是在过程或函数里面调用自身;

2)在使用递归时,必须有一个明确的递归结束条件,称为递归出口.

 

递归分为两个阶段:

1)递推:把复杂的问题的求解推到比原问题简单一些的问题的求解;

2)回归:当获得最简单的情况后,逐步返回,依次得到复杂的解.


而迭代一句话解释就是更新变量的旧值,一般多见于循环结构。


递归自己调用自己的这种特性,使得在求解问题的时候通常会形成解空间上的一颗二叉树,在枚举过程中较为多见,我用一道题目加以说明。

Problem Description
The "Harry Potter and the Goblet of Fire" will be on show in the next few days. As a crazy fan of Harry Potter, you will go to the cinema and have the first sight, won’t you?

Suppose the cinema only has one ticket-office and the price for per-ticket is 50 dollars. The queue for buying the tickets is consisted of m + n persons (m persons each only has the 50-dollar bill and n persons each only has the 100-dollar bill).

Now the problem for you is to calculate the number of different ways of the queue that the buying process won't be stopped from the first person till the last person. 
Note: initially the ticket-office has no money. 

The buying process will be stopped on the occasion that the ticket-office has no 50-dollar bill but the first person of the queue only has the 100-dollar bill.
 

Input
The input file contains several test cases. Each test case is made up of two integer numbers: m and n. It is terminated by m = n = 0. Otherwise, m, n <=100.
 

Output
For each test case, first print the test number (counting from 1) in one line, then output the number of different ways in another line.
 

Sample Input
3 03 13 30 0
 

Sample Output
Test #1:6Test #2:18Test #3:180

这道题目就很有代表性,先贴出我的代码。

#include <iostream>using namespace std;int a[200];int queue = 0;int m  = 0;int n  = 0;bool countArray(int p){    //int sum = 0;    /*for(int i =0;i<p;++i)    {        if(a[i] == 100)        sum++;    }    int temp = p-sum;    return (temp>sum);*/    for(int i =0;i<p;++i)    {        int sum = 0;        for(int j =0;j<=i;++j)        {            if(a[j] == 100)            sum++;        }        int temp = i - sum + 1;        if(temp < sum)        return false;    }    return true;}int collect(){    int sum = 0;    for(int i = 0;i<m+n;++i)    {        if(a[i] == 50)        sum++;    }    return sum;}void enumAll(int p){    if(p == m+n && countArray(m+n) && collect() == m  )    {        queue += 1;        return;    }    else if(p < m+n)    {        a[p] = 100;        //if(!countArray(p))        //{          //  a[p] = 50;        //}        enumAll(p+1);        a[p] = 50;        enumAll(p+1);    }}int fullSort(int n){    int sum = 1;    for(int i = 1;i<=n;++i)    {        sum = sum*i;    }    return sum;}int main(){    cin >> m >> n;    enumAll(0);    int result = 0;    if(m != 0 && n!= 0)    {        result = fullSort(m)*fullSort(n)*queue;    }    else if(n = 0 && m != 0)    {        result = fullSort(m) * queue;    }    else if(m = 0)    {        result = 0;    }    cout << result;    return 0;}

题目是英文,但静下心来读还是很好懂的,这道题,写出主要的程序我估计用了半个多小时,可debug却花了整整2个小时,我注释掉的部分都是些曾经的错误,在这里和大家分享一下心得。首先把对结果的约束条件尽量放到递归出口中进行判断,我们并不是要剪枝,只是在最后加以筛选,比如以上题为例,它要求拿50元的有m人,拿100元的有n人,我们不必在一边递归的同时一边想着限制条件,而是可以大胆地把这个放到最后的递归出口进行判断,很简洁,对不对。其次,还有一个比较坑的,这道题,如果没有看样例输入输出的话,你会认为m = 3,n = 0时,只有一种情况,结果是6种,它把每个人看做不同的个体,因此还要乘以3!。

明天我还会继续递归算法,否则,这个月说好的6篇博文怎么实现呢?敬请期待吧!


0 0
原创粉丝点击