(PAT)1111. Online Map(迪杰斯特拉算法)

解决在线地图推荐最短和最快路径问题的算法实现,基于迪杰斯特拉算法。输入包含地图交叉路口数量、街道数量及详细街道信息,输出最短距离和最短时间路径。当最短路径不唯一时,选择最快的一条;当最快路径不唯一时,选择经过最少交叉路口的一条。代码中特别考虑了路径记录的方法。
摘要由CSDN通过智能技术生成

不用模板徒手码代码真TM刺激。。PAT,我有句MMP不知当讲不当讲。

迪杰斯特拉,一个非常不错的算法,老迪也是个牛人,哎呀,跑题了。。不懂DJ算法的话,参考:迪杰斯特拉算法

1111. Online Map (30)

时间限制
300 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Input our current position and a destination, an online map can recommend several paths. Now your job is to recommend two paths to your user: one is the shortest, and the other is the fastest. It is guaranteed that a path exists for any request.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers N (2 <= N <= 500), and M, being the total number of streets intersections on a map, and the number of streets, respectively. Then M lines follow, each describes a street in the format:

V1 V2 one-way length time

where V1 and V2 are the indices (from 0 to N-1) of the two ends of the street; one-way is 1 if the street is one-way from V1 to V2, or 0 if not; length is the length of the street; and time is the time taken to pass the street.

Finally a pair of source and destination is given.

Output Specification:

For each case, first print the shortest path from the source to the destination with distance D in the format:

Distance = D: source -> v1 -> ... -> destination

Then in the next line print the fastest path with total time T:

Time = T: source -> w1 -> ... -> destination

In case the shortest path is not unique, output the fastest one among the shortest paths, which is guaranteed to be unique. In case the fastest path is not unique, output the one that passes through the fewest intersections, which is guaranteed to be unique.

In case the shortest and the fastest paths are identical, print them in one line in the format:

Distance = D; Time = T: source -> u1 -> ... -> destination

Sample Input 1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
3 4 0 3 2
3 9 1 4 1
0 6 0 1 1
7 5 1 2 1
8 5 1 2 1
2 3 0 2 2
2 1 1 1 1
1 3 0 3 1
1 4 0 1 1
9 7 1 3 1
5 1 0 5 2
6 5 1 1 2
3 5
Sample Output 1:
Distance = 6: 3 -> 4 -> 8 -> 5
Time = 3: 3 -> 1 -> 5
Sample Input 2:
7 9
0 4 1 1 1
1 6 1 1 3
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 1 3
3 2 1 1 2
4 5 0 2 2
6 5 1 1 2
3 5
Sample Output 2:
Distance = 3; Time = 4: 3 -> 2 -> 5
题目大意:给你一张图,找出从起点到终点最短距离(如果不唯一,找出其中用时最短的,这个保证唯一),输出距离和相关路径。再找出从起点到终点用时最短的距离(如果不唯一,找到其中经过节点最少的,这个保证唯一)。如果两者路径一样,输出格式参考样例2。

解题思路:单纯求最短距离和最短时间非常简单,但最短路径里找用时最短的,这个也简单,多加个判断。但要记录路径,我是开个数组记录每个节点前一个节点的位置。找最短时间也简单,但要找经过节点最少的,也是多开个数组记录节点数。

上代码,注意看注释:

#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cstring>
using namespace std;

struct Node
{
    int id,len,time;
}node;

int N,M;
vector<Node> vv[505];
int state,s,e;

queue<int> que;
stack<int> sta,sta2;
int dis[505],mytime[505];//分别用来记录其它节点到起点的距离和时间
int from[505],totimes[505],from2[505];//两个from用来记录每个节点前一个点的id,totimes用来记录每个节点从起点起经过了几个节点

int dj1(int flag)
{
    dis[s]=0; mytime[s]=0;
    que.push(s);
    while(!que.empty())
    {
        int ind=que.front();
        for(int i=0;i<vv[ind].size();i++)
        {
            int now=vv[ind][i].id;
			//处理距离模块
            if(flag==1)
            {
                if(dis[now]==-1 || dis[now]>dis[ind]+vv[ind][i].len || (dis[now]==dis[ind]+vv[ind][i].len && mytime[now]>mytime[ind]+vv[ind][i].time))
                {
                    dis[now]=dis[ind]+vv[ind][i].len;
                    mytime[now]=mytime[ind]+vv[ind][i].time;
                    from[now]=ind; //记录来源
                    que.push(now);
                }
            }
			
			//处理时间模块
            else
            {
                if(mytime[now]==-1 || mytime[now]>mytime[ind]+vv[ind][i].time || (mytime[now]==mytime[ind]+vv[ind][i].time && totimes[ind]+1<totimes[now]))
                {//cout<<"###"<<endl;
                    mytime[now]=mytime[ind]+vv[ind][i].time;
                    totimes[now]=totimes[ind]+1;
                    from2[now]=ind; //记录来源
                    que.push(now);
                }
            }
        }
        que.pop();
    }
    if(flag==1)
        return dis[e];
    else
        return mytime[e];
}
int dj2()
{

}

int main()
{
    cin>>N>>M;
    for(int i=0;i<M;i++)
    {
        scanf("%d%d%d%d%d",&s,&e,&state,&node.len,&node.time);
        node.id=e;
        vv[s].push_back(node);
        if(!state)//不是单向
        {
            node.id=s;
            vv[e].push_back(node);
        }
    }
    int nn;
    scanf("%d%d",&s,&e);
	//初始化
    memset(dis,-1,sizeof(dis));
    for(int i=0;i<501;i++)
        mytime[i]=0x37777777;
	
    int ans1=dj1(1); //距离
    printf("Distance = %d",ans1);
	//路径逆向放入栈中 即得到正向路径
    nn=e;
    while(true)
    {
        sta.push(nn);
        nn=from[nn];
        if(nn==s)
            break;
    }
    sta.push(nn);
	
	//初始化
    memset(mytime,-1,sizeof(mytime));
    memset(totimes,0,sizeof(totimes));
    int ans2=dj1(0); //时间
    //路径逆向放入栈中 即得到正向路径
    nn=e;
    while(true)
    {
        sta2.push(nn);
        nn=from2[nn];
        if(nn==s)
            break;
    }
    sta2.push(nn);
	
	//输出模块
    if(sta==sta2)
    {
        printf("; ");
        printf("Time = %d: ",ans2);

        printf("%d",sta2.top());
        sta2.pop();
        while(!sta2.empty())
        {
            printf(" -> %d",sta2.top());
            sta2.pop();
        }
        printf("\n");
    }
    else
    {
        printf(": %d",sta.top());
        sta.pop();
        while(!sta.empty())
        {
            printf(" -> %d",sta.top());
            sta.pop();
        }
        printf("\nTime = %d: ",ans2);

        printf("%d",sta2.top());
        sta2.pop();
        while(!sta2.empty())
        {
            printf(" -> %d",sta2.top());
            sta2.pop();
        }
        printf("\n");
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值