N个人过河问题

问题描述: 有一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸。而东岸
边有一条小船。  船太小了,一次只能乘坐两人。每个人都有一个渡河时间T,船划到对岸的时间等于船上渡河时间较
长的人所用时间, 现在已知N个人的渡河时间T,Oliver想要你告诉他,他们最少要花费多少时间,才能使所有人都过河。 

    注意,只有船在东岸(西岸)的人才能坐上船划到对岸。

解题:

假设N个旅行者的过河时间分别为(已排序){T0, T2, T3, T4 ... T[n-1]},N个旅行者过河的最快时间为sum。 从简单入手,如果N = 1, sum = T1;如果N = 2,  sum = max(T1, T2);如果N = 3, sum = T1+T2+T3。如果N > 3,考虑最慢和次慢两个人的过河方法。共有两种方案。

  第一种,最快和次快的人先过去(用时T[1]),然后最快的人回来(用时T[0]),接着最慢和次慢的人过去(用时T[n-1]),最后次快的人回来(用时T[1],然后一起过去(用时T[1])。整理后为T[0] + T[1] + T[1] + T[n-1]+T[1]。

第二种,最快和最慢的过去(用时T[n-1]),然后最快的回来(用时T[0]),接着最快和次慢的人过去(用时T[n-2]),最后最快的人回来(用时T[0]),然后一起过去(用时T[1])。整理后为T[0] + T[0] + T[n-1] + T[n-2]+T[1]。

递归解法:

  int crossRiver(int *T,int n)
{
if (n==1)
{
return T[0];
}
else if(n == 2)
{
return T[0] + T[1];
}
else if(n == 3)
{
return T[0] + T[1]+T[2];
}
else{
int t1 = T[0] + T[1] + T[1] + T[n - 1]+T[1];   //方案1  
int t2 = T[0] + T[0] + T[n - 1] + T[n - 2]+T[1]; //方案2  
int t = t1 > t2 ? t2 : t1;


return crossRiver(T, n - 2) + t;
}


}


int ShortTime(int T[],int n)
{
sort(T, T + n);//排个序  
if (n==1)
{
return T[0];
}
else if (n==2)
{
return T[1];
}
else if (n==3)
{
return T[0] + T[1] + T[2];
}
else{
return crossRiver(T, n);
}


}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
限时过河问题是一个经典的算法问题,可以用Matlab进行求解。 假设有n个人需要过一座桥,每个人过桥的时间不同,其中一个人需要一盏灯,一次只能过一人,过桥时需要灯,且灯在任何时候只能由一个人扛着,所有人过桥的总时间最短。 我们可以使用贪心算法来解决这个问题。首先将所有人按照过桥时间从小到大排序,让最快的人先过桥,然后再让他把灯回来给下一个人使用。接下来让次快的人过桥,再把灯回来,以此类推,直到所有人都过桥为止。 下面是一个简单的Matlab代码实现: ```matlab % n个人过桥,每个人的时间为t,灯的人为light n = 5; t = [1 3 5 7 9]; light = 1; % 将所有人按照时间从小到大排序 [t, idx] = sort(t); % 记录每个人过桥的时间 time = zeros(1, n); % 记录灯的位置:0表示在此岸,1表示在对岸 lamp = zeros(1, n); lamp(1) = 1; % 让人依次过桥 for i = 1:n % 如果这个人灯,就把灯回来 if i == light lamp(1) = 0; lamp(idx(i)) = 0; time(i) = t(i); % 如果这个人灯,就等待灯回来 else while lamp(i-1) == 0 continue; end lamp(idx(i)) = 1; time(i) = t(i); end end % 输出每个人过桥的时间和总时间 disp('每个人过桥的时间:'); disp(time); disp(['总时间:', num2str(sum(time))]); ``` 运行结果: ``` 每个人过桥的时间: 1 3 5 7 9 总时间:25 ``` 这段代码实现了限时过河问题的求解,通过计算每个人过桥的时间和总时间,我们可以得到最优解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值