//micosoft.h
/********************************************************************
* 文件名: micosoft.h
* 文件描述: 解微软面试题
* 创建人: 陈泽丹, 2006年3月26日, (QQ:82314038)
* 版本号: 1.0
* 修改记录:
********************************************************************/
/*-------------------------------------------------------------------
问题介绍:
每个飞机只有一个油箱,飞机之间可以相互加油(注意是相互,没有加油机),一箱油可供一架飞机绕地球飞半圈。
问:为使至少一架飞机绕地球一圈回到起飞时的飞机场,至少需要出动几架飞机?
(所有飞机从同一机场起飞,而且必须都安全返回机场,不允许中途降落,中间没有飞机场)
解题思路:
递归方案。设最终有一架能飞完全一圈,而一架最多装油半圈,故它需
要补充半圈油。羊毛出在羊身上,我们来找那头羊好了,嘻嘻。这半圈油当然
出在别的飞机身上,而别的飞机又抽别别的飞机。。。递归终止条件:当某一架飞
机被抽完其它飞机“仅仅所需的油”后,它还能安全飞回基地。递归结束。
具体细节:
一架飞机在1/4全程点上如能满油(即得到1/4的补充量),它就能飞回。因为3/4点同样可补到1/4的量(注意地球是圆的,可两边补)。 那么1/4全程点时它可抽其它飞机的,然后它可飞回了,但然后其它飞机飞不回怎么办呢?再用解决刚才那"飞全程飞机的方法"来解决其它飞机,递归下去...直到有飞机被人抽后还能够油飞回基地。(注意每次补充量只需它总的补充量的一半就行哦)
--------------------------------------------------------------------*/
/*===================================================================
Max 最大加油量 (注意在本题时加油量的单位就是路途,故全程是2,则半圆为1
,即最大加油量为1)
journey: 需飞的路程
oil: 本身被其它抽油后的存油量
fly(): 调用飞机的函数
count计量飞机数。
====================================================================*/
#ifndef HEADER_FLY
#define HEADER_FLY
#include <iostream.h>
#define Max 1
int count=0;
void fly(double journey, double oil);
#endif
//-----------------------------------------------------------------------
//micosoft.cpp
#include "micosoft.h"
void fly(double journey, double oil)
{
if ( journey-oil>0 )
{
count++;
fly(journey-oil,Max-0.5*(journey-oil));
}
}
void main()
{
cout<<"从同一地点出发的相同型号的飞机,可是每架飞机装满油";
cout<<"只能绕地球飞半周,飞机之间可以加油,加完油的飞机必";
cout<<"须回到起点。问至少要多少架次,才能满足有一架绕地球一周。";
count++;
fly(2,1);
cout<<count<<endl;
}
看到这道题,很有趣,试着求解一番。
关于飞机加油问题:
1.首先确定问题可以求解。
要使所有飞机安全飞回那么,加油点之间的距离肯定不能超过1次加满油飞行的距离。
可以肯定加油点除了 1/2处不能设定外,其余各点都可以设定加油点。(理由见后面)
于是问题有解。
2.
假设飞机从按照逆时针,从东飞到西。
有n架飞机同时起飞。
地球一圈长度为f
对逆时针飞行加油点。
第k架在x[k]处返回。
y[k]是从x[k-1]处开始飞行到有飞机折回的距离
如下关系如下:
x[1]= y[1];
x[2]= x[1]+y[2];
x[3]= x[2]+y[3];
x[k]= x[k-1] + y[k];(k=1,2,3...n-1);
x[k] < 0.5f;
k的最大取值是 n-1因为 2台飞机只能一次油,3台飞机最多可以加两次油。
要保证飞机能飞最远,就是使每一架飞机在折回后不折回的飞机的油是满的。
所以有:
0.5f - 2*y[1] = (n-1)*y[1];
0.5f - 2*y[2] - x[1] = (n-2)*y[2];
0.5f - 2*y[3] - x[2] = (n-3)*y[3];
0.5f - 2*y[k] - x[k-1] = (n-k)*y[k];(k=1,2,3...n-1);
变形一下
0.5f = (n-1+2)*y[1];
0.5f = (n-2+2)*y[2] + x[1];
0.5f = (n-3+2)*y[3] + x[2];
0.5f = (n-k+2)*y[k] + x[k-1] ;
(k=1,2,3...n-1);
解出 x[k]的表达式:
x[1] = y[1] = 0.5f/(n+1) ;
x[2] = 0.5*2/(n+1);
x[3] = 0.5*3/(n+1);
....
x[k] = 0.5f*k/(n+1);
由于 x[k] 必须小于 0.5f 否则谁都不愿意开那架飞机了。
就是说 k/(n+1) 只须小于 1即可(但不能等于1),
要想使x[k]尽量远,那么就要保证 k/(n+1)尽量大。
k和n都比必须使正数。而且k最大只能取 n-1
所以k=n时,k/(n+1) = (n-1)/(n+1)
这时可知,n趋向于无穷大时,(n-1)/(n+1) 趋向于1,
(而且也可以得知 n越大k才能越大)
因此加油点可以遍布整个右半球,但是1/2点处不能到达。
对顺时针飞行加油点。
同样的思考方式。同样的结果。
同时还有结论:
根据
y[k] = x[k] - x[k-1] = 0.5f/(n+1)
可知:
n越多,那么加油站点之间的距离就会越小(得到加油站点之间距离表达式跟次数无关的无关的结论我也很诧异)。
由前面的推论:
x[k] = 0.5f*k/(n+1);
可知最远的加油站是
x[k] = 0.5f*(n-1)/(n+1);
他也只和 n相关。
所以 x[k] 越远他需要的 飞机数量越多。
由于飞机满油能飞,0.5f所以要想达到最优化,
就要使飞机落在0.5f里面的区域的每一点都比区域外面的点的需要的飞机数要少(假定在需要比较的点设置加油站的话)
由于两边都是对称的,而且从出发点到地球的另一端点的过程种,各点(如果要设置加油站的话)需要的飞机数使递增的。
所以,我们可以轻松的推定,0.5f 均匀的分布在地球另一端点的两边。(这部分也可以用证明,时间关系,暂略)
所以只需要在两个方向安排同样数量n的飞机布置最远的加油点在离出发点 1/4 f的地方或更远一点就可以了。
问题演变成
x[k] >= 1/4 f
x[k] < 0.5f
取 k的最小整数值
x[k] 的最远点的表达式是 x[k] = 0.5f*(n-1)/(n+1);
也即
0.5f*(n-1)/(n+1) >= 1/4 f
0.5f*(n-1)/(n+1) < 0.5fn>0
求最小的 n
解之得
n >= 3
所以n得最小取值是3
也就是 需要 6架次。 但最少只需要3架飞机。
过程如下:
逆时针起飞第一次加油点在 x[1] = 1/8 f处。然后有一架飞机返回。
第二次加油在 x[2] = 1/4 f处,一架飞机返回。
在逆时针飞行的飞机飞过 0.5f 处时,顺时针派出3架飞机,(可以重用以前的飞机,如果允许的话)
第一次加油处也是 1/8 f 一架飞机飞回
第二次在1/4f 同时 逆时针飞行的飞机也到达,将油均分后每个飞机一半的油。同时飞回来。
可以抵达出发点。
另解:
为使至少一架飞机绕地球一圈回到起飞时的飞机场,至少需要出动几架飞机?(所有飞机从
同一机场起飞,而且必须安全返回机场,不允许中途降落,中间没有飞机场)
1、飞机1、飞机2等飞机n为飞机的个数
2、把整个圆(飞行轨道)周等分为8份,分别定为O点(起飞点),依次为A、B、C、D、E、
F、G
设想一下,按题目要求一架飞机要想不加油安全的飞并且安全返回,能飞行最远距离是一个
圆周的1/4,既飞行度距离是OB;如果给另外一架飞机加油的话它只能飞行1/8的距离OA。这
些前提的存在,再根据题意就可推出如下的飞行放案:
1、首先同时从O点起飞三架飞机,当他们飞到A点时,飞机1、飞机2将继续飞行,飞机三给
飞机1、飞机2加油,各加1/4的油,这样飞机1和飞机2就满油了;飞机3用剩下的1/4(飞到
A点已经用去了1/4的油)的油刚好能飞回起点。
2、飞机1、飞机2继续飞行。飞到B点时,飞机1将继续飞行,飞机2给飞机1加油,加1/4的油
,这样飞机1的油箱又会加满油;飞机2用剩下的2/4(飞到B点又用去了1/4的油再加上给飞
机1加的1/4油)的油刚好飞回起点。
3、飞机1继续飞行,因为满油,所以可以飞半圈飞到F点。
4、当飞机1飞到D点的时刻,同时从O点反方向派出三架飞机,飞机4、飞机5、飞机6。这样
能保证飞机1飞到F点时刚好有两架飞机到达F点。(飞机4、飞机5、飞机6是沿着OG的方向飞
行)
5、当飞机4、飞机5、飞机6飞到G点时,飞机6同时给飞机4、飞机5加油。飞机4、飞机5满油
继续飞,飞机6安全飞回O点。
6、飞机1、飞机4、飞机5同时飞到F点,此时刻各加飞机的油料为
飞机1——0 飞机4——3/4 飞机5——3/4
这下就方便了,飞机4和飞机5分别给飞机1一点点1/4的油料,三架飞机就安全的飞回O点了
。
至此,飞机1完成了环球飞行,并且其他飞机也都安全到达起飞点,总共派出了6架飞机。