数据结构编程实验(第3版)
上QQ阅读APP看书,第一时间看更新

2.3 构造法模拟

构造法模拟属于一种比较复杂的模拟方法,因为它需要完整而精确地构造出反映问题本质的数学模型,根据该模型设计状态变化的参数,计算模拟结果。

由于数学模型建立了客观事物间准确的运算关系,因此其效率一般比较高。

若模拟对象、过程变化和数学模型比较简单,则构造法模拟就非常类似于递推,也属于简单模拟。

【2.3.1 Bee】

在非洲,有一个非常特殊的蜂种。每年,这个蜂种的一只雌性蜜蜂会生育一只雄性蜜蜂,而一只雄性蜜蜂会生育一只雌性蜜蜂和一只雄性蜜蜂,生育后它们都会死去。

现在科学家意外地发现了这一特殊蜂种的一个“神奇的雌蜂”,它是不死的,而且仍然可以像其他雌蜂一样每年生育一次。科学家想知道在n年后会有多少蜜蜂。请写一个程序,计算n年后雄蜂的数量和所有的蜜蜂数。

输入

每个输入行包含一个整数n(≥0),输入以n=-1结束,程序不用对n=-1进行处理。

输出

输出的每行有两个数字,第一个数字是n年后雄蜂的数量,第二个数字是n年后蜜蜂的总数。这两个数字不会超过232

在线测试:UVA 11000

试题解析

从蜜蜂繁衍的时间顺序看,本题似乎是一道过程模拟题。但由于蜜蜂按规律繁衍,需要构造相应的数学模型,因此本题实际上属于构造性模拟题。

由于每个测试用例仅一个整数n,输入的结束标志为-1,因此在输入第1个测试用例的年数n后,程序进入while(n>-1)的循环结构。循环体计算过程如下:

1)设雌蜂数a的初始值为1,雄蜂数b的初始值为0。注意答案可能超过标准整数类型的上限,因此a和b的类型设为长整型。

2)i从0递推至n-1,i+1年后的雌蜂数为上一年的雄蜂数+1,雄蜂数为上一年的蜜蜂总数。注意辗转赋值(c=1+b;d=a+b;a=c;b=d)。

3)输出n年后的雄蜂数a和蜜蜂总数a+b。

4)输入下一个测试组的年数n。

参考程序


#include <iostream>                   //预编译命令
using namespace std;                  //使用 C++标准程序库中的所有标识符
int main(void)
{
    int n;
    cin >> n;                         //输入年数
    while (n > -1) {
        long long a = 1;              //雌蜂数的初始值为1,雄蜂数的初始值为0。注意答案
                                      //可能超过长整型数据上限
        long long b = 0;
        for (int i = 0; i < n; i++) { //递推
            long long c, d;
            c = 1 + b;                //计算下一年雌蜂和雄蜂的数量
            d = a + b;
            a = c;
            b = d;
        }
        cout<<b<<' '<<a+b<<endl;      //输出n年后雄蜂的数量和蜜蜂的总数
        cin >> n;                     //输入下一个年数
    }
    return 0;
}

构造法模拟的关键是找到数学模型。问题是,能产生正确结果的数学模型并不是唯一的,从不同的思维角度看问题,可以得出不同的数学模型,而模拟效率和编程复杂度往往因数学模型而异。即便有了数学模型,求解该模型的准确方法是否有现成算法、编程复杂度和时间效率如何,也都是在模型选择中需要考虑的问题。