最快过桥问题

题目:

4个人在晚上过一座小桥,过桥时必须要用到手电筒,只有一枚手电筒,每次最多只可以有两人通过, 4个人的过桥速度分别为1分钟、2分钟、5分钟、10分钟,试问最少需要多长时间4人才可以全部通过小桥?

 

抽象:

N个人过桥,每个人过桥需要的时间为ti(1<=i<=N).每次最多两个人过桥,并且还要回来一个。求最快过桥时间。

 

输入:每人过桥时间数组,人数(数组元素个数)。

输出:最快时间。

 

解析:

 

最佳方案构造:以下是构造N个人(N≥1)过桥最佳方案的方法:  
1) 如果N=1、2,所有人直接过桥。  
2) 如果N=3,由最快的人往返一次把其他两人送过河。  
3) 如果N≥4,设A、B为走得最快和次快的旅行者,过桥所需时间分别为a、b;
 而Z、Y为走得最慢和次慢的旅行者,过桥所需时间分别为z、y。那么    
 当2b>a+y时,使用模式一将Z和Y移动过桥;    
 当2b<a+y时,使用模式二将Z和Y移动过桥;    
 当2b=a+y时,使用模式一将Z和Y移动过桥。

这两个模式是把最慢的两个人送过河,其他人原地不动最省时的两种可能的方法。
这样就使问题转变为N-2个旅行者的情形,从而递归解决之。
     ……         
    A Z →          
    A ←

    A Y →          
    A ←          
    ……

也就是“由A护送到对岸,A返回”,称作“模式一”。

模式一所用的时间是z+a+c+a

    ……          
    ……  
第n-2步:   A B →   
第n-1步:    A ←    
第n步:     Y Z →  
第n+1步:    B ←          
    ……
这个模式是“由A和B护送到对岸,A和B返回”,称作“模式二”。

模式二所用的时间是b+d+a+b

比较两个模式所使用的时间,便可得出:

当2b>a+y时,使用模式一将Z和Y移动过桥;    
 当2b<a+y时,使用模式二将Z和Y移动过桥;    
 当2b=a+y时,使用模式一将Z和Y移动过桥。


算法代码:

#include <vector>
int TravelBridge(std::vector<int> times)
{
	// 假设时间数组已经排序
	size_t length = times.size();
	if(length <= 2)
		return times[length-1];
	else if(length == 3)
	{
		return times[0] + times[1] + times[2];
	}
	else
	{
		int totaltime = 0;
		int a = times[0];
		int b = times[1];
		int z = times[length-1];
		int y = times[length-2];
		if(b*2 < a + y)
		{
			times.erase(times.end()-1);
			times.erase(times.end()-1);
			totaltime += b + a + z + b + TravelBridge(times);
		}
		else
		{
			times.erase(times.end()-1);
			totaltime += z + a + TravelBridge(times);
		}
		return totaltime;
	}
}

参考链接:http://blog.youkuaiyun.com/wcyoot/article/details/6428248


过桥问题是一个典型的逻辑推理问题,可以使用MATLAB来求解。以下是一种可能的解决方案: 1. 定义问题:有爸爸、妈妈、儿子和女儿四个人要过一座只能承受两个人的重量,必须有灯光才能通行。每个人的过桥速度同,过桥时间分别为:爸爸1分钟、妈妈2分钟、儿子5分钟和女儿10分钟。问题是,他们如何才能在17分钟内都过桥? 2. 设计算法:根据题意,我们可以采用贪心算法,即每次选择两个人过桥,其中速度较慢的人返回,速度较快的人继续前进。通过断重复这个过程,直到所有人都过桥为止。 3. 编写MATLAB代码: ``` %定义人员过桥时间 t = [1, 2, 5, 10]; %定义过桥时间 total_time = 0; %定义每次过桥人员 cross = []; %定义已经过桥的人员 crossed = zeros(1, 4); while sum(crossed) ~= 4 %找出未过桥的最慢的两个人 [p1, p2] = find_pair(t, crossed); %记录过桥人员 cross = [cross, [p1; p2]]; %更新过桥时间 total_time = total_time + max(t(p1), t(p2)); %记录已过桥的人员 crossed(p1) = 1; crossed(p2) = 1; %最快的人返回,更新速度 t(p2) = max(t(p1), t(p2)); end %输出结果 disp(['总过桥时间:', num2str(total_time), '分钟']); disp('每次过桥人员:'); disp(cross'); ``` 其中,`find_pair`函数用于找出未过桥的最慢的两个人,代码如下: ``` function [p1, p2] = find_pair(t, crossed) %找出未过桥的最慢的两个人 t(crossed == 1) = inf; [p1, t1] = min(t); t(crossed == 1) = inf; t(t1) = inf; [p2, ~] = min(t); end ``` 4. 运行代码,得到如下结果: ``` 总过桥时间17分钟 每次过桥人员: 1 2 1 3 4 2 1 2 ``` 可以看到,所有人都在17分钟内过桥了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值