1 | 2 | 3 | |
---|---|---|---|
1 | 0 | r(1,2) | min{r(1,2)+ r(2,3),r(1,3)} |
2 | 0 | r(2,3) | |
3 | 0 |
例6:租用游艇问题(例)
问题描述: 长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n. 游客可在这些游艇出租站租用游艇, 并在下游的任何一个游艇出租站归还游艇. 游艇出租站i到出租站j之间的租金为r(i,j), 1<=i<j<=n. 试设计一个算法, 计算出从游艇出租站1到游艇出租站n所需的最少租金, 并分析算法的计算复杂性.
算法设计: 对于给定的游艇出租站i到游艇出租站j的租金r(i,j), 1<=i<j<=n. 计算出租站1到n所需的最少租金.
数据输入: 第1行有一个正整数n, n<=200, 表示有n个游艇出租站. 接下来n-1行是r(i,j), 1<=i<j<=n.
结果输出: 游艇出租站1到n最少租金.
一、确定状态:
终点:坐标为n;
子问题:设f[i] [j]为从i到j最小得分, f[i] [j] = min{f[i] [k] + f[k+1] [j], r[i] [j]};
二、确定转移方程:
f[i] [j] = min{f[i] [k] + f[k] [j], r[i] [j]};
三、确定初始条件和边界情况:
初始条件:f[1] [1] = 0;
边界情况:f[i] [i+1] = r[i] [i+1];
四、确定计算顺序:
从小到大,填表斜行
代码:
#include <iostream>
#include <cstring>
using namespace std;
int f[205][205] ;
void Init(){
memset(f, 0, sizeof(f));
}
int Min(int x, int y)
{
return x<y?x:y;
}
void Dp(int n)
{
int i, j, k, l;
for(l = 1; l < n; l++)
{
for(i = 1; i+l <= n; i++)
{
j = i + l;
for(k = i+1; k < j; k++)
{
f[i][j] = Min(f[i][k] + f[k][j], f[i][j]);
}
}
}
}
int main(int argc, char** argv) {
Init();
int n;
cin>>n;
int i, j;
for (i = 1; i <= n - 1; i++)
{
for(j = i+1; j <= n; j++)
{
cin>>f[i][j];
}
}
Dp(n);
cout<<f[1][n]<<endl;
return 0;
}
总结
同样是oj上的题,这题挺常规的,就是之前提到的斜填表加最值型问题,因为之前填石子的问题掉坑里还没改好就先发这个了。