飞机加油问题,据说是微软的面试题。

 

//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点(起飞点),依次为ABCDE

FG

 

 

设想一下,按题目要求一架飞机要想不加油安全的飞并且安全返回,能飞行最远距离是一个

圆周的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架飞机。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值