题目:长江港口出租游艇,有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;
}