动态规划之租船问题
【问题】 长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i < j<=n。试设计一个算法,计算出从游艇出租站1 到游艇出租站n所需的最少租金。
【分析】 假设p[i][j]为从i点开始租船,到j点还船的最小费用(最优值),那么p[i][j+1] = min { p[i][j] + m[j][j+1], m[i][j+1]},其中m[i][j]为输入的数据,表示从第i个租船点到第j个还船点的直接费用。很明显,在这个式子中,我们通过比较两个值的大小便可得出当前还船点与第i个租船点之间的最小费用。因此,最终的结果为p[0][n-1](从下标0开始记录)。
【程序执行模拟】
假设输入数据为:
4
5 14 23
5 12
8
以下为输入的数据分布(即m[i][j])
租船点\还船点
0 1 2 3
0 0 5 14 23
1 0 0 5 12
2 0 0 0 8
3 0 0 0 0
p[i][j]:
租船点\还船点
0 1 2 3
0 0 5 10 17
1 0 0 5 12
2 0 0 0 8
3 0 0 0 0
【程序】
#include<iostream>
using namespace std;
int min(int a, int b) {
return a < b ? a : b;
}
int main() {
int n;
cin>>n;
//m[i][j]为初始数据
int **m = new int*[n];
for (int i = 0; i < n; i++) {
m[i] = new int[n];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
m[i][j] = 0;
}
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
cin>>m[i][j];
}
}
//p[i][j]为起点i到终点j的最小金额
int **p = new int*[n];
for (int i = 0; i < n; i++) {
p[i] = new int[n];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
p[i][j] = 0;
}
}
for (int i = 0; i < n; i++) {
int minNum = m[0][i];
for (int j = 0; j < i; j++) {
minNum = min(minNum, p[0][j] + m[j][i]);
}
p[0][i] = minNum;
}
cout<<p[0][n - 1];
}