算法学习笔记8——游艇出租站最小租金(多源点最短路径问题)

问题描述:
游艇租用问题:长江旅游俱乐部在长江上设置了N个游艇出租站0,1,2,…,N-1,游客在这些站中租用游艇,并在下游的任何一个游艇出租站归还,游艇出租站i到游艇出租站j之间的租金为fee(i,j),0≤i<j≤N-1;试使用动态规划法求出从游艇出租站0到游艇出租站N-1所需的最少租金;
实现提示:
设游艇出租站有N个,而且每两个站的租金都是不一样的,用f(i,j)表示每两个站之间的租金费用。当要租用游艇从一个站到另外一个站时,采取不同的停靠站策略就有不同的租金。例如从第一个站到第三个站,租金是15元,但是第一个站到第二个站的租金只需5元,第二到第三个站的租金要7元,因此可采用先到第二个站,把游艇归还,然后再从第二个站租用游艇到第三个站,因此我们总共需要的费用就是5+7=12元,比直接从第一个站到第三个站要花15元更经济,也就是最少花费。
这是一个优化问题,并且具有最优子结构,表示前n-1个站的最优解,那么前n个站的最优解一定包含前n-1个站的最优解,并且它们具有重叠性。
可以参考课本的“多源点最短路径问题”的解法。设用数组minFee[n][n]表示站点间的最少租金,fee[n][n]表示站点间的直达租金,minFee初始与fee相等。可推导出动态规划函数:
minFee[i][j]=min{Fee[i][j],minFee[i][k]+minFee[k][j]} 0≤k≤n-1
如下为租金费用, 为了方便检验结果的正确性,请用如下租金矩阵,从0到5站的最优结果为17元。
int fee[n][n]=
{{0,3,15,18,29,34},
{3,0,1, 17,18,23},
{15,1,0,10,12,15},
{18,17,10,0,4, 7},
{29,18,12,4,0, 1},
{34,23,15,7,1, 0}};
完整代码:

#include <iostream>
#include<stdio.h>
#include<windows.h>
#include<iomanip>
using namespace std;
#define n 6

void floyd(int fee[n][n], int minFee[n][n])
{
	int i, j, k;
	for (i = 0; i < n; i++)
		for (j = 0; j < n; j++)
			minFee[i][j] = fee[i][j];
	for (k = 0; k < n; k++)//进行n次迭代
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				if (minFee[i][k] + minFee[k][j] < minFee[i][j])
					minFee[i][j] = minFee[i][k] + minFee[k][j];
}

int main()
{
	int p, q;
	int fee[n][n]{ {0,3,15,18,29,34},
				 {3,0,1, 17,18,23},
				 {15,1,0,10,12,15},
				 {18,17,10,0,4, 7},
				 {29,18,12,4,0, 1},
				 {34,23,15,7,1, 0} };//租金矩阵
	int minFee[n][n];
	LARGE_INTEGER nFreq;

	LARGE_INTEGER nBeginTime;

	LARGE_INTEGER nEndTime;

	double time;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&nBeginTime);

	floyd(fee,minFee);

	QueryPerformanceCounter(&nEndTime);

	time = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);

	cout <<"从0到5站的最少花费为"<<minFee[0][5]<<endl;
	cout <<"程序运行时间(纳秒)"<<time; 
}

运行结果:
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值