- 数据结构编程实验(第3版)
- 吴永辉 王建德编著
- 915字
- 2021-08-13 17:23:59
2.1 直叙式模拟
直叙式模拟就是要求编程者按照试题给出的规则或求解过程,直接进行模拟。这类试题不需要编程者设计精妙的算法来求解,但需要编程者认真审题,不要疏漏任何条件。
由于直叙式模拟只需严格按照题意要求模拟过程即可,因此大多属于简单模拟题。当然,并非所有直叙式模拟题都属于简单模拟题,关键是看模拟对象所包含的动态变化的属性有多少。动态属性越多,难度越大。
【2.1.1 Speed Limit】
Bill和Ted踏上行程,但他们汽车的里程表坏了,因此他们不知道驾车走了多少英里。幸运的是,Bill有一个正在运行的跑表,可以记录他们的速度和驾驶了多少时间。然而,这个跑表的记录方式有些古怪,需要他们计算总的驾驶距离。请编写一个程序完成这项计算。
例如,他们的跑表显示如下:
这表示开始的2小时他们以20英里的时速行驶,然后的6-2=4小时他们以30英里的时速行驶,再以后的7-6=1小时他们以10英里的时速行驶,所以行驶的距离是2×20+4×30+1×10=40+120+10=170英里。总的时间耗费是从他们旅行开始进行计算的,而不是从跑表计数开始计算的。
输入
输入由一个或多个测试用例组成。每个测试用例开始的第一行为一个整数n(1≤n≤10),后面是n对值,每对值一行。每对值的第一个值s是时速,第二个值t是总的耗费时间。s和t都是整数,1≤s≤90且1≤t≤12。t的值总是增序。n的值为-1表示输入结束。
输出
对于每一个数据集合,输出行驶距离,然后是空格,最后输出单词“miles”。
试题来源:ACM Mid-Central USA 2004
在线测试:POJ 2017,ZOJ 2176,UVA 3059
试题解析
本题是一道十分简单的直叙式模拟题,计算过程就是模拟跑表的运行来计算总里程:若上一个记录的驾驶时间为z,当前记录的速度为x、驾驶时间为y,则当前驾驶的距离为(y-z)×x,将该距离累计入总里程ans。
参考程序
#include <iostream> //预编译命令 using namespace std; //使用 C++标准程序库中的所有标识符 int main( ) //主函数 { //主函数开始 int n, i, x, y, z, ans; //声明整型变量n、i、x、y、z、ans // 多个测试用例,每次循环处理一个 while (cin >> n, n > 0) //反复输入当前组的数据对数,直至输入结束 { ans = z = 0; // 模拟跑表运行来计算 for (i = 0; i < n; i++) //输入和计算当前测试用例 { cin >> x >> y; //输入当前时速和总耗费时间 ans += (y - z) * x; //累计总里程 z = y; //记下当前总耗费时间 } cout << ans << "miles" << endl; //输出当前数据组的总里程 } return 0; }
【2.1.2 Ride to School】
北京大学的许多研究生都住在万柳校区,距离主校区——燕园校区有4.5公里。住在万柳的同学或者乘坐巴士,或者骑自行车去主校区上课。由于北京的交通情况,许多同学选择骑自行车。
假定除Charley以外,所有的同学从万柳校区到燕园校区都以某个确定的速度骑自行车。Charley则有一个不同的骑车习惯——他总是要跟在另一个骑车同学的后面,以免一个人独自骑车。当Charley到达万柳校区的大门口的时候,他就等待离开万柳校区去燕园校区的同学。如果他等到这样的同学,他就骑车跟着这位同学;如果没有这样的同学,他就等待去燕园校区的同学出现,然后骑车跟上。在从万柳校区到燕园校区的路上,如果有骑得更快的同学超过了Charley,他就离开原先他跟着的同学,加速跟上骑得更快的同学。
假设Charley到万柳校区大门口的时间为0,给出其他同学离开万柳校区的时间和速度,请你给出Charley到达燕园校区的时间。
输入
输入给出若干测试用例,每个测试用例的第一行为N(1≤N≤10000),表示除Charley外骑车同学的数量。以N=0表示输入结束。每个测试用例的第一行后面的N行表示N个骑车同学的信息,形式为:
Vi[空格]Ti
Vi是一个正整数,Vi≤40,表示第i个骑车同学的速度(kph,每小时公里数),Ti则是第i个骑车同学离开万柳校区的时间,是一个整数,以秒为单位。在任何测试用例中总存在非负的Ti。
输出
对每个测试用例输出一行:Charley到达的时间。在处理分数的时候进1。
试题来源:ACM Beijing 2004 Preliminary
在线测试:POJ 1922,ZOJ 2229
试题解析
本题没有数学公式和规律,通过直接模拟每个同学去往燕园校区的情景,得出Charley从万柳校区到燕园校区的时间。所以对每个测试用例,从Charley到万柳校区大门的时间0开始计时,求出每个同学到达燕园校区所用的时间,最少的时间就是Charley从万柳校区大门到燕园校区的时间。
设前i-1个同学中最早到达燕园校区的时间为min;第i个同学的车速为v,离开万柳校区的时间为t,则该同学到达燕园校区的时间。若x<min,则调整min为x。显然,按照这一方法依次计算所有同学的到达时间,最后得出的min即Charley到达的时间。
需要提醒的是,本题测试用例中有一个陷阱:当Ti取负值时,对于Charley到达燕园校区的时间没有影响,应予剔除。
参考程序
#include <iostream> //预编译命令 #include <cmath> using namespace std; //使用 C++标准程序库中的所有标识符 int main() //主函数 { const double DISTANCE = 4.50; //定义两个校区的距离 while(true) //循环处理每个测试用例 { int n; //定义整型变量n scanf("%d", &n); //输入除Charley外的骑车同学数 if (n == 0) break; //若输入结束,则退出 double v, t, x, min = 1e100; //定义双精度实数v、t、x,min初始化为10100 for(int i = 0; i < n; ++i) //循环处理组内的每个骑车同学 { scanf("%lf%lf", &v, &t); //输入第i个骑车同学的速度和离开万柳校区的时间,计 //算该同学到达燕园校区的时间x。若小于min,则min //调整为x if (t >= 0 && (x = DISTANCE * 3600 / v + t) < min) min = x; } printf("%.0lf\n", ceil(min)); //输出Charley到达的时间 } return 0; }
[1] 1英里=1609.344米。——编辑注