游艇出租站最少费用,动态规划算法!

题目:长江港口出租游艇,有1,2....n个出租站点,游客可在这个某出租站点租游艇,然后在下游任一出租站点归还游艇。游艇出租站i到j的出租费用为r(i,j);1<=j<j<=n,计算港口1到n的最小费用。


分析:假设出租站点1到出租站点n的最短费用不是为1到n的直通费用,就是说最短费用是在1到n中间,至少在某一个出租点还了游艇,然后又继续租游艇到站点n,所以最少费用满足min=min(Min(i,j)+Min(j,n)),1<j<n;所以此题满足动态规划的最优子结构性质。当我们求出租站1到出租站n的最少费用时候,我们需要知道出租站2到出租站n的最少费用,并且需要知道3-n的最少费用,当我们求出租站2到出租站n的最少费用的时候,又需要知道出租站3到出租站n的最少费用,所以此题也满足动态规划的第二个性质:子问题重叠!


思路:假设数组m(i,j)表示出租站i到出租站j的最少费用,则问题具有这种最优解结构:

m(1,n)=min(r(1,j)+m(j,n));      1<j<n;

自顶向下的方法:
// 港口最少费用.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <stdio.h>
#include <limits.h>   //有个表示int类型最大值的宏在这个头文件里面

int FindMinest(int (*p)[10], int (*m)[10], int k, int n);
int Min(int a, int b);
int main()
{
	int n;
	int p[10][10] = { 0 };   //保存出租站之间的直通费用
	int m[10][10] = { 0 };    //保存出租站之间的最短费用
	scanf_s("%d", &n);
	for (int i = 0; i < n-1; ++i) {  
		for (int j = i+1; j < n; ++j) {
			scanf_s("%d", &p[i][j]);  //输入出租站之间的直通出租费用
		}
	}
	int min = FindMinest(p, m, 0, n-1);
	printf("%d", min);
    return 0;
}
//自顶向下的方法
int FindMinest(int(*p)[10], int(*m)[10], int k, int n) {//这个函数的作用就是找到港口K到港口n的最小费用
	int min = INT_MAX;
	if (k == n) {
		return 0;
	}
	if (m[k][n] > 0) {
		return m[k][n];
	}
	for (int i = k + 1; i <= n; ++i) {
		min = Min(min, p[k][i] + FindMinest(p, m, i, n));

	}
	m[k][n] = min;
	return min;
}
int Min(int a, int b) {
	return a < b ? a : b;
}

自底向上的方法:
// 港口最小费用-自底向上.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <stdio.h>
#include <limits.h>   //有个表示int类型最大值的宏在这个头文件里面

int FindMinest(int(*p)[10], int(*m)[10], int n);
int Min(int a, int b);
int main()
{
	int n;
	int p[10][10] = { 0 };   //保存港口之间的直通费用,二维数组初始化为全0
	int m[10][10] = { 0 };    //保存港口之间的最短费用  ,二维数组初始化为全0
	scanf_s("%d", &n);
	for (int i = 0; i < n - 1; ++i) {
		for (int j = i + 1; j < n; ++j) {
			scanf_s("%d", &p[i][j]);
		}
	}
	int min = FindMinest(p, m, n - 1);	//n是港口数,但是数组下标用到的最大值是n-1
	printf("%d", min);
	return 0;
}
//自底向上的方法     
int FindMinest(int(*p)[10], int(*m)[10], int n) {//这个函数的作用就是找到港口1到港口n的最小费用
	int min;
	for (int i = n-1; i >= 0; --i) {
		min = INT_MAX;              //INT_MAX是头文件limit.h中定义的宏,意思就是int类型的最大值,定义成最大值就是为了下面第一次比较的时候不会出现比他大的数,
									//如果min定义成5,那如果最下费用是9,那么返回的结果是5不是9
		for (int j = i + 1; j <= n; ++j) {
			min = Min(min, p[i][j] + m[j][n]);     
		}
		m[i][n] = min;
	}
	return min;
}
int Min(int a, int b) {
	return a < b ? a : b;
}

以上2段代码均在vs2015中编译通过,下图为运行测试结果



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值