奥数 --- 传令兵问题(第三届华中地区全国程序设计邀请赛)

Problem 1556 - J - A Naughty Dog
Time Limit: 3000MS   Memory Limit: 65536KB  
Total Submit: 3  Accepted: 3  Special Judge: No
Description

 One day Ryan picked up a dog, a very naughty and lively dog. He named it Rainer.

 

Rainer the dog loves running here and there, and chases everything under its sight. Another 'one day', Ryan and Rainer took a slow walk in a fragrant garden.

 

While Ryan was indulged in the million colors of flowers, Rainer catched plenty of butterflies flying in a line overhead, as usual, it tried to chase them again.

 

Assume the line of butterflies were a definitely straight line, and Rainer the dog and the butterflies moved in the same direction. Rainer started at the tail of the butterflies line, after it moved to the head of the line, it turned around immediately, moved to the tail again. In this period, they all moved with a different but constant speed. 

 

If the length of butterflies line is A miles, and the line moved B miles in the litter chasing game, how long had Rainer moved in total?

Input
The input consists of one or more test cases.

First line of each case contains two values A and B. (  1 <= A <= 1000000, 0 <= B <= 1000000 )
Output
For each case, print the answer in one line, and please keep two places of decimal of it.
Sample Input
1 0
Sample Output
2.00
Hint
Source
Ryan
 
【题目来源】
http://acm.whu.edu.cn/land/problem/detail?problem_id=1556
【题目大意】
大毛养了一只灰常可爱的dog,一天他带着他的小狗出去玩,这只狗不安分,去追蝴蝶,就有了这道题:有一排蝴蝶,总长度为A,小狗去追蝴蝶,蝴蝶和小狗同向运动,当小狗追上最前面一只蝴蝶后,他又返回,直到遇到最后一只蝴蝶。已知蝴蝶长度为A,蝴蝶
运动距离为B,求整个过程中小狗运动的路程。
【题目分析】
其实这是一道经典的奥数题,而且是小学级别的,不过他还有一个别称是“难倒清华大学生的小学生题目”,由此可见难度不是很简单。(不过我真的怀疑那个清华大学生也太水了吧)。
传令兵问题:有一支大军,首位长达50m。大军以匀速前进时,一个传令兵从队伍的最后面,骑着快马向前跑,到队首传达一个紧急命令。任务完成后,他马不停蹄,立即回到他原来的位置。而当他回到原位时,大军也正好向前推进的50m。
问:传令兵一共走了多少路?(传令兵始终匀速运动)
 
乍一看很简单,不就是高中物理的追击问题和相遇问题的组合吗,额,确实是这样的,但仔细看了以后发现用高中物理知识根本解不出来,因为给的条件根本不够,所以说这是一道数学题。
首先我们将其分为两个过程,第一个是追及问题,第二个是相遇问题。
一、追及问题
设在追及阶段队伍前进了a,那么士兵前进了A+a。
二、相遇问题
在相遇阶段队伍前进了B-a,那么士兵走了A-(B-a),因为相遇问题的总长为A,而队伍走了B-a,剩下的是士兵走的。
又因为是匀速的,所以有以下式子(速度比等于路程比):(A+a)/(a)=(A-(b-a))/B-a。
根据这个式子可以解出a,那么剩下的问题都不是问题了。
解这个方程要用到二元一次方程求根公式,不是很难。
如果你进一步化解推倒聚能得出最后的公式: 士兵行走的路程=A+sqrt(A*A+B*B)
是不是很神奇?所以说看到许多很难的题别人四五行代码就解决了,这说明别人用了更多的时间去推导计算,而不是写代码,这也体现了数学在ACM中的重要性。
 
 
#include<iostream>

#include<cstdio>

#include<cmath>

using namespace std;

int main()

{

    int A,B;

    while(cin>>A>>B!=NULL)

    {

        double ans;

        ans=(double)A+sqrt(A*A+B*B);

        printf("%.2lf\n",ans);



    }

    return 0;

}

 

 

另附:

【推导过程】

设,队速为S,兵速为r*s;队伍长L

则,兵追到队首的时间为t1 = L/(r-1)s

兵再折返到队尾的时间为t2 = L/(r+1)s

总时间t =t1+t2=L/s * 2r/(r^2-1)

队行总距离D1 =t*s= L * 2r/(r^2-1) => r^2 - 2(L/D1)r - 1=0

=> r = (L + sqrt(L^2 + D1^2) )/ D1

兵行总距离D2=t*r*s=D1*r= L + sqrt(L^2 + D1^2)

另外一种神推理:(数学不好的可以忽略)

用勾股定理去解,方程实在复杂了点:
如果把队伍前进1米所用时间看成一个时间单位,则总时间为50;
假设传令兵的速度为x,那么传令兵绕1圈的路程为:50x;
无论从何地出发,绕1圈用的时间相同。
我们假设传令兵从队伍的后角开始出发:
第一段:是一个追及问题:
路程差为50m,速度差为:x-1,所用时间为:50/(x-1);

第三段:是一个相遇问题:
路程和为50m,速度和为:x+1,所用时间为:50/(x+1);

第二段与第四段:
当传令兵在队伍前面或队伍后面时,传令兵行走路线分别如图所示:

总时间减去第一段与第三段的时间,则为前后时间和:
50-50/(x-1)-50/(x+1)
队伍前进的速度为1,传令兵的速度为x,可知:
队伍前进的路程即下面直角边长度为:50-50/(x-1)-50/(x+1)
传令兵前进的路程即斜边的长度为:[50-50/(x-1)-50/(x+1)]*x
根据勾股定理:两直角边的平方和=斜边的平方,可得方程。再求x的值。
而50x即为传令兵绕1圈的路程。
看这架势,方程很复杂,是个四次方程。谁愿意解谁就去解。

可以看出这种方法显然在程序设计中会很麻烦,所以说这种方法不是为算法而设计的(⊙o⊙)…

 

 

你可能感兴趣的:(程序设计)