游船费问题

来源:互联网 发布:东方法学知乎 编辑:程序博客网 时间:2024/04/28 02:14

问题描述

   某旅游城市在长江边开辟了若干个旅游景点。一个游船俱乐部在这些景点都设置了游艇出租站。游客可在这些游船出租站租用游船,并在下游的任何一个游船出租站归还游船,从一个游船出租站到下游的游船出租站间的租金明码标价。你的任务是为游客计算从起点到终点站间的最小租船费用。

输入

    输入文件有若干组数据,每组测试数据的第一行上有一个整数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 100using 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]);
}

0 0