问题描述
某旅游城市在长江边开辟了若干个旅游景点。一个游船俱乐部在这些景点都设置了游艇出租站。游客可在这些游船出租站租用游船,并在下游的任何一个游船出租站归还游船,从一个游船出租站到下游的游船出租站间的租金明码标价。你的任务是为游客计算从起点到终点站间的最小租船费用。
输入
输入文件有若干组数据,每组测试数据的第一行上有一个整数n(1<=n<=100),表示上游的起点站0到下游有n个游船出租站
1,2,。。。,n。接下来有n行,这n行中的第1行有n个整数,分别表示第0站到第1,2,3,。。。,n站间的游船租金;第2行有n-1个整数,分别表示第1站到第2,3,4,。。。n站间的游船租金;。。。。;第n-1行有2个整数,表示第n-2站到第n-1、n站间的游船租金;第n行有1个整数,表示第n-1站到第n站间的游船租金。一行上有两个整数之间是用空格隔开的。两组测试数据之间无空行。
输出
对输入文件中的每组测试数据,先在一行上输出“Case #:”,其中“#”测试数据的编号(从1开始)。再输出一行,内容是该情况下游客从起点站到终点站间的最少租船费用。
输入样例
3
2 3 6
1 3
2
3
4 7 9
4 5
6
输出样例
Case 1:
5
Case 2:
9
思路一,用f[i][j]表示从i到j的租船费用,a[i][j]表示i到j的最少游船费用,然后从第i站到第j站要么直接到达要么通过一个中转站k从i到k再从k到j。
得到状态转移方程为
a[i][j] = min((a[i][k]+a[k][j]),f[i][j]);
#include <iostream> #include <stdio.h> #include <algorithm> #define maxn 100 using namespace std; int f[maxn][maxn],a[maxn][maxn];//f[i][j]表示从i到j的租船费用,a[i][j]表示i到j的最少游船费用 int main(void) { int n; int i,j,k; int num = 1; while(cin>>n) { //int num = 1; for(i = 0; i < n; i++) { for(j = i+1; j <= n; j++) { cin>>f[i][j]; a[i][j] = f[i][j];//顺便初始化a[i][j]数组。 } } for(i = 0; i < n; i++) { for(k = i+1; k < n-1; k++) for(j = k+1; j <= n; j++) { a[i][j] = min((f[i][k]+f[k][j]),f[i][j]); } } cout<<"Case "<<num<<":"<<endl; num++; cout<<a[0][n]<<endl; } //cout << "Hello world!" << endl; return 0; }我们可以看到中间因为加了一个中转站多以是一个三重循环,效率较低而且100万的数据很可能超时!
所以我们有了另一个方法。
思路二,
用一个一位数组m[i]表示起点站到第i站的最小游船租金。则要么直接到达,要么需要经过中转站k;
得到状态转移方程为m[i] = min(m[i],m[k]+f[k][i]);
一个二重循环得到结果
代码如下
for(i = 0; i < n; i++)
{
m[i] = f[0][i];
for(j = n-i; j > 0; j--)
m[i] = min(m[i],m[j]+f[j][i]);
}
原文地址:http://blog.csdn.net/sheldon761642718/article/details/45022599