微软面试题-过桥问题

来源:互联网 发布:彩票缩水软件大全 编辑:程序博客网 时间:2024/04/29 14:07
找工作中,可能要笔试,,有相关智力题,所以做了几道,今天发现了一个过桥问题,好像是一个比较经典的问题,微软用它做过笔试题。
过桥问题
问题:S个人晚上过桥,他们都站在桥的一端,桥上最多只能让N个人过桥。他们有一个手电筒,无论是一个人走还是k(k<=N)个人走,都需要手电筒。但人过桥后,手电筒不能扔过去,只能派人传过去。假设第i个人过桥的时间是Ti,则过桥的最短时间T(S)为?
解:不妨假设过桥时间Ti<=Tj(i<j)。
N递归方案:如果S<=N,则T(S)=max(T1,…,TS)=TS,否则T(S)=T(S-N)+min(S中最后N人过桥时间)。S中最后N人过桥时间最短方式:前N个人过桥,第一个人把手电筒带回,然后最后N个人拿着手电过桥,然后由第2个人把手电带过来。这个时间为F1=max(T1,…,TN)+ T1+max(TS-N+1,…,TS)+ T2= TN+T1+TS+T2
另外还有一种N-1递归方案:如果S<=N,则T(S)=max(T1,…,TS)=TS,否则T(S)=T(S-N+1)+min(S中最后N-1人过桥时间),具体过法是:第一个人和最后N-1个人过桥,然后第一个人拿着手电筒过来,所需时间F2= max(TS-N+2,…,TS)+T1= TS+T1
因为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;
}
程序运行结果:


原创粉丝点击