行车路线

行车路线

[问题描述]
  小明和小芳出去乡村玩,小明负责开车,小芳来导航。
  小芳将可能的道路分为大道和小道。大道比较好走,每走1公里小明会增加1的疲劳度。小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走s公里小明会增加s2的疲劳度。
  例如:有5个路口,1号路口到2号路口为小道,2号路口到3号路口为小道,3号路口到4号路口为大道,4号路口到5号路口为小道,相邻路口之间的距离都是2公里。如果小明从1号路口到5号路口,则总疲劳值为(2+2)2+2+22=16+2+4=22。
现在小芳拿到了地图,请帮助她规划一个开车的路线,使得按这个路线开车小明的疲劳度最小。
[基本要求]
输入格式:
  输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。
接下来m行描述道路,每行包含四个整数t, a, b, c,表示一条类型为t,连接a与b两个路口,长度为c公里的双向道路。其中t为0表示大道,t为1表示小道。保证1号路口和n号路口是连通的。
输出格式
输出一个整数,表示最优路线下小明的疲劳度。
样例输入
6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1
样例输出
76
样例说明
  从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。
要求:
(1)要求从文本文件中输入;
(2)采用适当的数据结构存储由输入数据中的道路所形成的图结构;
(3)编写尽可能优的算法,处理好连续走小道造成的疲劳值的指数增长(提示:基于迪杰斯特拉算法进行改进即可完成本题);
(4)除严格按题目要求进行输出以外,还要求输出最优路线的路径,以及从出发点到各个点的最小疲劳值。

数据结构
利用图的邻接矩阵进行存储
typedef struct ArceCell
{
VRType adj;
VRType bs;//存储大道,小道
}ArcCell , AdjMatrix[ MAX_VERTEX_NUM ][ MAX_VERTEX_NUM ];
typedef struct
{
VertexType vexs[MAX_VERTEX_NUM];//顶点向量
AdjMatrix arcs;
int vexnum , arcnum;
}MGraph;

算法设计思想
利用图的邻接矩阵来存储路口和每条路的疲劳值;
设置数组存储每个路径的前一个结点。
利用迪杰斯特拉算法,设置循环,遍历矩阵,每次将当前路口的最小疲劳值置为最大,从路口1开始遍历没有走过的路口,若u-v这条路为小路,若u前面与1号路口间有小道相连,则求它们和的平方,若还有大道相连,则直接相加,再取两次的疲劳值中小的值与前面的结果相加,即为这个路口到1号结点的最小疲劳值,再重复上述步骤,直到遍历所有路口为止。

测试数据和结果
测试数据:
6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1

结果:
在这里插入图片描述
算法时间复杂度
void ShortestPath_DIJ( int s, MGraph G )
时间复杂度:O(n²)

代码如下:
我注释应该写的挺全的,可能略有些繁琐,如果有不明白的可以留言问我。

#include <stdio.h>
#include <stdlib.h>
#include<iostream>
#include<fstream>
#include <iomanip>
using namespace std;
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM  80//最大路口数
#define VRType long long
#define VertexType int
int road[ MAX_VERTEX_NUM];
int num=0;
long long now_p[MAX_VERTEX_NUM];//存储储存出发点到各个点的疲劳值
bool if_visited[MAX_VERTEX_NUM];// 存储当前路口是否已被访问
long double bestLength = INFINITY;// 最短路径初始化为无穷大
long long small_rode[MAX_VERTEX_NUM] ;//每个结点到出发点的小道路径之和
long long square_road[MAX_VERTEX_NUM];
long long big_road[MAX_VERTEX_NUM];//每个结点到出发点的大道路径之和
long long pass_road[MAX_VERTEX_NUM];//存储当前的疲劳值
int pre[MAX_VERTEX_NUM ];

typedef struct ArceCell
{
    VRType adj;
    VRType bs;//存储大道,小道
}ArcCell , AdjMatrix[ MAX_VERTEX_NUM ][ MAX_VERTEX_NUM ];
typedef struct
{
    VertexType vexs[MAX_VERTEX_NUM];
    AdjMatrix arcs;
    int vexnum , arcnum;
}MGraph;
//创建图
void CreateGraph( MGraph &G )
{
    int i, j;
    long long a[4];
    int k1, k2;
    ifstream read_in;
    read_in.open( "text5.txt" );
    if ( !read_in )
    {
        cout<< "文件读取失败!" <<endl;
        return;
    }
    read_in >> G.vexnum;
    read_in >> G.arcnum;
    for ( i = 1; i <= G.vexnum ; i++ )
    {
        for ( j = 1; j <= G.vexnum; j++)
        {
           G.arcs[i][j].adj = INFINITY;
        }
    }
    for( i = 1; i <= G.vexnum; i++)
        {
           G.vexs[i]=i;
        }
    for( i = 1; i <= G.arcnum; i++ )
    {
            for ( j = 0; j < 4; j++ )
            {
                read_in >> a[j];
            }
            k1 = a[1];
            k2 = a[2];
            if( a[0]==0 )//t为0表示大道
            {
                G.arcs[k1][k2].bs=0;
                G.arcs[k1][k2].adj = a[3];
                G.arcs[k2][k1].bs=0;
                G.arcs[k2][k1].adj = a[3];
            }
            else if( a[0]==1 )//t为1表示小道
            {
                G.arcs[k1][k2].bs=1;
                G.arcs[k1][k2].adj = a[3];
                G.arcs[k2][k1].bs=1;
                G.arcs[k2][k1].adj = a[3];
            }
    }
    cout<< "无向图创建成功!" <<endl;
    cout<< "顶点数: " << G.vexnum <<endl;
    cout<< "边数:" << G.arcnum <<endl;
    cout<< "顶点: ";
    for ( i = 1; i <= G.vexnum; i++ )
    {
         cout<< G.vexs[i] <<" ";
    }
    cout<<endl<<"******************邻接矩阵****************"<<endl;
    k1 = 0;
    for ( i = 1; i <= G.vexnum ; i++ )
    {
        for ( j = 1; j <= G.vexnum; j++)
        {
            if( G.arcs[i][j].adj==INFINITY )
               printf( "%-2d ", k1 );
            else
               printf( "%-2lld ", G.arcs[i][j].adj );
        }
        cout<<endl;
    }
    cout<<"******************************************"<<endl;
    read_in.close();
}

long long square(long long x)
{
    return x*x;
}
//利用迪杰斯特拉算法求疲劳值
void ShortestPath_DIJ( int s, MGraph G )
{
    int i, v;
    long long x, y, Shortest;
    for( i=0; i<MAX_VERTEX_NUM; i++ )
    {
        big_road[i] = INFINITY;
        small_rode[i] = INFINITY;
        square_road[i] = INFINITY;
        pass_road[i] = INFINITY;
        if_visited[i] = false;
        pre[i] = 0;
    }
    pass_road[s]=0;
    big_road[s]=0;
    small_rode[s]=0;
    while(1)
    {
        int u=0;
        Shortest = INFINITY;
        for( i=1; i<=G.vexnum; i++)//更新最短距离
        {
            if(if_visited[i]==false&&pass_road[i]<Shortest)
            {
                u=i;
                Shortest=pass_road[i];
            }
        }
        if( u==0 )//若未更新
            break;
        road[num] = u;
        num++;
        if_visited[u] = true;//将u号路口置为已被访问
        //开始主循环,每次求得路口到1号路口的最短路径
        for ( v=1; v<=G.vexnum; v++ )
        {
            if( G.arcs[u][v].adj!=INFINITY && if_visited[v]==false )
            {
                x = INFINITY;
                y = INFINITY;
                if ( G.arcs[u][v].bs==1 )//小道
                {
                    if ( small_rode[u]!=INFINITY )//如果这个路口和1号路口有小道相连
                    {

                        if ( pre[u]==0 )//若前面没有小道
                           x = square( small_rode[u] + G.arcs[u][v].adj );
                        else
                            x = big_road[pre[u]] + square(  small_rode[u]+G.arcs[u][v].adj );
                    }
                    if ( big_road[u]!=INFINITY)//如果这个路口和1号路口有大道相连
                        y = square( G.arcs[u][v].adj ) +  big_road[u];
                    if ( x<y )
                    {
                        small_rode[v] = min(  small_rode[v],  small_rode[u]+G.arcs[u][v].adj );
                        square_road[v] = min( x, square_road[v] );//存储之前遍历的小道路径的和的平方
                    }
                    else
                    {
                        small_rode[v] = min(  small_rode[v], G.arcs[u][v].adj);
                        square_road[v] = min( y, square_road[v] );
                        pre[v] = u;
                    }
                    pass_road[v] = min( square_road[v] ,  big_road[v] );
                }
                else//当前道路是大道
                {
                    if ( big_road[u]!=INFINITY )
                       x =  big_road[u] + G.arcs[u][v].adj;
                    if ( small_rode[u]!=INFINITY )
                       y = square_road[u] + G.arcs[u][v].adj;
                    long long mini = min(x,y);
                    big_road[v] = min(  big_road[v], mini );
                    pass_road[v] = min( square_road[v],  big_road[v] );
                }
            }
        }
    }
    return;
}

int main()
{
    int i;
    MGraph G;
    CreateGraph(G);
    ShortestPath_DIJ( 1, G );
    cout<< pass_road[G.vexnum]<<endl;
    cout<< "最优路劲:";
    for ( i=0; i<G.vexnum; i++ )
         cout<< road[i]<<" ";
    cout<<endl<< "输出出发点到各个点的疲劳值:";
    for ( i=1; i<=G.vexnum; i++ )
         cout<< pass_road[i]<<" ";
    return 0;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值