动态规划之游艇租用问题

问题描述

长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i 对于给定的游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i 由文件提供输入数据。文件的第1行中有1个正整数n(n<=200),表示有n个游艇出租站。接下来的n-1行是r(i,j),1<=i (例如: 3
5 15
7
表示一共有3个出租站点,其中
第1个站点到第2个的租金为5
第1个站点到第3个的租金为15
第2个站点到第3个的租金为7)


证明最优性原理
假设从游艇出租站1到出租站n的最优方案为在x1,x2,x3…xk处归还并在此租用。若x1,x2,x3…xk-1不是游艇从出租站1到出租站n-1的最优方案,则设其最优方案为S,则费用应比假设的最优方案更低。因此,x1,x2,x3…xk-1必然为游艇从出租站1到出租站n-1的最优方案。
划分子问题
初始子问题:第一个站点到第一个站点的租金为0
下一阶段的子问题:
第一个站点到第二个站点的租金为5
第一个站点到第三个站点:1,直接从第一个站点到第三个战斗的租金15;2,第一个站点,第二个战点再到第三个站点的租金5+7=12;上述情况取最小值。

确定动态方程
令arc[i][j]表示直接从第i个站点到第j个站点的租金;
令cost[i]表示从第一个站点到第i个站点所需最少租金;
【1】初始子问题,当i=1时,cost[1]=0;
【2】下一阶段的子问题,当i>1时,
cost[i]=min{arc[1][i],cost[k]+arc[k][i]} [其中1

注意
不要陷入误区,求第一个站点到第i个站点时,取1-3-i,则3–i阶段取其直接到达的租金,而非在这种情况下考虑3–i如何最优。后续过程中考虑1–4--i,1–5--i……的过程中,已将上述情况考虑在内。动态规划,即在上一步最优的情况下直接走下一步,记录所有的情况,并进行比较。


源代码

#include
#include
using namespace std;
//3
//5 15
//7
//表示一共有3个出租站点,其中
//第1个站点到第2个的租金为5
//第1个站点到第3个的租金为15
//第2个站点到第3个的租金为7

int main()
{
	int n; int fare[200][200];
	int cost[200];
	ifstream f1("C:\\Data\\3.txt");
	ofstream f2("C:\\Data\\4.txt");
	f1 >> n;
	for (int a = 0; a < n; a++)
	{
		for (int b = a; b < n; b++)
		{
			if (a == b)
			{
				fare[a][b] = 0;
			}
			else
			{
				f1 >> fare[a][b];
			}
		}
	}
	cost[0] = 0;
	if(n>1)
	cost[1] = fare[0][1];
	if (n > 2) {
		int temp = 0;
		for (int i = 2; i < n; i++)
		{
			cost[i] = fare[0][i];
		}
		for (int a = 2; a < n; a++)
		{
			for (int b = a - 1; b > 0; b--)
			{
				temp = cost[b] + fare[b][a];
				if (temp < cost[a])
					cost[a] = temp;
			}
		}
	}
	cout << "从游艇租用站1到租用站" << n << "所需最少租金为" << cost[n-1] << "\n";
	f2<< cost[n-1] << "\n";
	f1.close();
	f2.close();
	return 0;
}

你可能感兴趣的:(实验)