微软过桥问题Dijkstra/倒水问题

微软过桥问题

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

思路:刚一看到这道题,思路比较狭窄,就拿着笔把人移过来再移过去,第一次做出的答案是19(错误答案).后来上网上去找参考答案,发现是17.网上的答案只给出得到17分钟的解决方式,并没有说出到底应该怎么样解这个答案才能百分百确定就是最少的长时?因此,开始乱想:穷举法,贪心法,参考《牧师与野人过河问题》,DFS,图论找最小路径法,乱蒙。最开始参照<牧师与野人>的算法,发现,无果。再用穷举法,发现转移状态实在太多,没有办法递归下去,然后用贪心选择,发现最后倒在vector.erase上面了,而且递归的时候没有办法恢复现场,因为需要在vector的中间删除一个元素,然后再恢复,并不像《字符串全排列》那样可以push_back,再pop_back就能恢复现场。最后想,既然无法恢复现场,那么不妨可以从一开始就不要破坏原来现场,而只是拷贝原来vector的一份拷贝,只对拷贝进行操作,那么递归返回时就没有必要恢复原来现场,当然原来现场也并没被破坏,这样一来,每次递归结束之后,我们可以得到一个过桥方案,递归堆栈中的内容被清除(当然对原来内容并没有任何影响,下一次可以继续正常递归而不需要担心原来内容被改变而带来的不确定后果)。其于这个方案可以得到下面的程序(贪心法)。

 

#include<vector>
#include<iostream>
using namespace std;

void removeKeyFromVec(vector<int>& veci,int key)
{
	for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); ++iter)
	{
		if( *iter == key)
		{
			iter = veci.erase(iter);//erase的使用要小心
			return ;
		}
	}
}

void CrossBridge(vector<int>& src, vector<int>& des, int size, int TimeSum)
{
	//程序出口,当只有2个人时,直接过桥
	if(size == 2)
	{
		cout<<"A->B:"<< src[0] << " AND " << src[1]<<endl;
		cout<<"Time : "<<TimeSum + max(src[0], src[1]) <<endl;
		cout<<endl;
		return ;
	} 
	//从size大小的数列中找出两个数的组合,例1,2,5有(1,2),(1,5),(2,5) 3种组合
	for(int i=0; i<size; i++)
	{
		for(int j=i+1; j<size; j++)
		{
			cout<<"i="<<i<<" j="<<j<<endl;
			//只操作src的拷贝,否则递归之后需要还原现场,较麻烦
			vector<int> srcTemp(src) ;
			vector<int> desTemp(des) ;
			
			int goTime1 = srcTemp[i] ;
			int goTime2 = srcTemp[j] ;
			//2人过桥
			desTemp.push_back(goTime1);
			desTemp.push_back(goTime2) ;

			cout<<"A->B: " << goTime1 <<" AND "<< goTime2 <<endl;

			removeKeyFromVec( srcTemp ,goTime1);
			removeKeyFromVec( srcTemp ,goTime2);

			int minBackTime = desTemp[0];
			for(int k=0 ; k<desTemp.size(); k++)
			{
				if( desTemp[k] < minBackTime)
				{
					minBackTime = desTemp[k];
				}
			}
			//1人返回
			srcTemp.push_back(minBackTime);
			removeKeyF
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
旅行商问题是一个经典的组合优化问题,目标是找到一条路径,使得旅行商能够经过所有城市并返回起始城市,同时路径的总长度最短。Dijkstra算法是一种用于解决赋权有向图的单源最短路径问题算法,可以用于解决旅行商问题。 下面是使用Dijkstra算法解决旅行商问题的步骤: 1. 初始化距离数组和访问数组。距离数组用于记录起始城市到其他城市的最短距离,访问数组用于标记已经访问过的城市。 2. 将起始城市的距离设为0,其他城市的距离设为无穷大。 3. 选择距离数组中未访问过的最小值,将其标记为已访问。 4. 更新距离数组。对于当前选择的城市,遍历其相邻的未访问城市,如果经过当前城市到达相邻城市的距离比之前记录的距离小,则更新距离数组。 5. 重复步骤3和步骤4,直到所有城市都被访问过。 6. 最后,距离数组中记录的就是起始城市到其他城市的最短距离。 下面是一个使用Dijkstra算法解决旅行商问题的示例代码: ```python import sys def dijkstra(graph, start): num_cities = len(graph) distances = [sys.maxsize] * num_cities visited = [False] * num_cities distances[start] = 0 for _ in range(num_cities): min_distance = sys.maxsize min_index = -1 for i in range(num_cities): if not visited[i] and distances[i] < min_distance: min_distance = distances[i] min_index = i visited[min_index] = True for i in range(num_cities): if not visited[i] and graph[min_index][i] != 0 and distances[min_index] + graph[min_index][i] < distances[i]: distances[i] = distances[min_index] + graph[min_index][i] return distances # 示例图的邻接矩阵表示 graph = [ [0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0] ] start_city = 0 distances = dijkstra(graph, start_city) print("起始城市到其他城市的最短距离:") for i, distance in enumerate(distances): if i != start_city: print(f"从城市 {start_city} 到城市 {i} 的最短距离为 {distance}") ``` 这段代码使用邻接矩阵表示城市之间的距离,通过调用`dijkstra`函数可以得到起始城市到其他城市的最短距离。在示例中,起始城市为0,输出结果为起始城市到其他城市的最短距离。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Raise

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值