微软面试题-过桥问题

本文解析了一个经典的过桥问题,探讨了不同人数过桥时如何在有限条件下以最短时间完成。通过递归算法实现了问题求解,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

找工作中,可能要笔试,,有相关智力题,所以做了几道,今天发现了一个过桥问题,好像是一个比较经典的问题,微软用它做过笔试题。
过桥问题
问题:S个人晚上过桥,他们都站在桥的一端,桥上最多只能让N个人过桥。他们有一个手电筒,无论是一个人走还是k(k<=N)个人走,都需要手电筒。但人过桥后,手电筒不能扔过去,只能派人传过去。假设第i个人过桥的时间是Ti,则过桥的最短时间T(S)为?
解:不妨假设过桥时间T i <=T j (i<j)。
N递归方案:如果S<=N,则T(S)=max(T 1 ,…,T S )=T S ,否则T(S)=T(S-N)+min(S中最后N人过桥时间)。S中最后N人过桥时间最短方式:前N个人过桥,第一个人把手电筒带回,然后最后N个人拿着手电过桥,然后由第2个人把手电带过来。这个时间为F 1 =max(T 1 ,…,T N )+ T 1 +max(T S-N+1 ,…,T S )+ T 2= T N +T 1 +T S +T 2
另外还有一种N-1递归方案:如果S<=N,则T(S)=max(T 1 ,…,T S )=T S ,否则T(S)=T(S-N+1)+min(S中最后N-1人过桥时间),具体过法是:第一个人和最后N-1个人过桥,然后第一个人拿着手电筒过来,所需时间F 2 = max(T S-N+2 ,…,T S )+T 1= T S +T 1
因为N递归方案不一定比N-1递归方案好,但N-1递归方案一定比N-2,…,1递归方案好(显而易见,能够照越多人过越好)
因此:
下去。
例1:S=4,N=2,四个人过桥时间依次为:1,2,5,10分钟。(微软面试题)
第一轮:F1=2+1+10+2=15,F2=10+1=11,T(4)=min{T(2)+15,T(3)+11}
第二轮:对于T(2)=2;对于T(3),F1=2+1+5+2=10,F2=1+5=6,所以T(3)=min{T(1)+10,T(2)+6}=min{11,8}=8。
代入第一轮,得出T(4)=min{2+15,8+11}=17
由于递归计算手算麻烦,编个简单c++程序如下(程序不排序,所以得严格输入):
#include<iostream.h>
int GetT(int *T,int n,int N,bool show)
{
    if(n<=N)
    {
       if(show)
       {
           for(int i=0;i<n;i++)
              cout<<i+1<<",";
           cout<<"-->>过去"<<"       "<<T[n-1]<<endl;
       }
        return T[n-1];
    }
    else
    {
       int F1=T[0]+T[1]+T[n-1]+T[N-1];
       int F2=T[n-1]+T[0];
       int T1=GetT(T,n-N,N,false)+F1;
       int T2=GetT(T,n-N+1,N,false)+F2;
       if(T1<T2)
       {
           if(show)
           {
              for(int i=0;i<N;i++)
                  cout<<i+1<<",";
              cout<<"-->>过去"<<"       "<<T[N-1]<<endl;
              cout<<1<<"把手电带回来"<<"       "<<T[0]<<endl;
              for(i=0;i<N;i++)
                  cout<<n-N+1+i<<",";
              cout<<"-->>过去"<<"       "<<T[n-1]<<endl;
              cout<<2<<"把手电带回来"<<"       "<<T[1]<<endl;
              GetT(T,n-N,N,true);
           }
           return T1;
       }
       else
       {
           if(show)
           {
              for(int i=1;i<N;i++)
                  cout<<n-N+i+1<<",";
              cout<<1;
              cout<<"-->>过去"<<"       "<<T[n-1]<<endl;
              cout<<1<<"把手电带回来"<<"       "<<T[0]<<endl;
              GetT(T,n-N+1,N,true);
           }
           return T2;
       }
    }
}
void main()
{
    int S;
    int N;
    int ret;
    cout<<"请输入总的过桥人数"<<endl;
    cin>>S;
    cout<<"请输入一次能过的人数"<<endl;
    cin>>N;
    int *T=new int[S];
    cout<<"请依次输入过桥的时间,按照从小到大顺序输入!"<<endl;
    for(int i=0;i<S;i++)
       cin>>T[i];
    cout<<"-----------------具体过桥方案为:------------------"<<endl;
    ret=GetT(T,S,N,true);
    cout<<"----------------"<<endl;
    cout<<"最少时间为:"<<ret<<endl;
    delete []T;
}
程序运行结果:


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值