基础实验8-1.2 直捣黄龙 (30分)-Dijkstra算法

 

 

 

 解题思路:Dijkstra算法

1、给城镇编号

2、转换成图

3、用Dijkstra算法求解

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MaxVex 200
#define INF 0x3f3f3f3f
int G[MaxVex][MaxVex];
int visit[MaxVex]= {0};
int path[MaxVex];
int cnt[MaxVex];
int num[MaxVex]= {0};
int sum[MaxVex]= {0};
int tmp[MaxVex]= {0};
char s[MaxVex][4];
int Nv,Ne;
int start,destination;
int getNum(char *c) {
    int i;
    for(i=0; i<Nv; i++) {
        if(!strcmp(s[i],c))
            return i;
    }
}

void Init() {
    char c1[4];
    char c2[4];
    scanf("%d %d %s %s",&Nv,&Ne,c1,c2);
    int i;
    for(i=0; i<Nv-1; i++) {
        scanf("%s%d",s[i],&sum[i]);
        tmp[i]=sum[i];
    }
    strcpy(s[Nv-1],c1);
    start=getNum(c1);
    destination=getNum(c2);
    memset(G,INF,sizeof(G));
    int v1,v2,x;
    for(i=0; i<Ne; i++) {
        scanf("%s %s %d",c1,c2,&x);
        v1=getNum(c1);
        v2=getNum(c2);
        G[v1][v2]=x;
        G[v2][v1]=G[v1][v2];
    }
    for(i=0; i<Nv; i++) {
        if(G[start][i]!=INF)
            cnt[i]=1;//start->i存在边,则初始化路径数为1 
    }
}
void Dijkstra(int start) {
    visit[start]=1;
    num[start]=1;
    int i,j,w;
    for(i=0; i<Nv; i++) {
        int MIN=INF;
        for(j=0; j<Nv; j++) {
            if(!visit[j]&&G[start][j]<MIN) {
                MIN=G[start][j];
                w=j;
            }
        }
        visit[w]=1;
        for(j=0; j<Nv; j++) {
            if(!visit[j]&&MIN+G[w][j]<G[start][j]) { //路径较短
                G[start][j]=MIN+G[w][j];//更新路径长度 
                cnt[j]=cnt[w];//统计路径数 
                path[j]=w;//记录上一个节点编号 
                sum[j]=sum[w]+tmp[j];//更新杀敌数
                num[j]=num[w]+1;//统计节点数 
            } else if(!visit[j]&&MIN+G[w][j]==G[start][j]) { //路径长度一致
                cnt[j]=cnt[w]+cnt[j];//统计路径数 
                if(num[w]+1>num[j]) { //经过节点较多
                    num[j]=num[w]+1;//统计节点数 
                    path[j]=w;//记录上一个节点编号
                    sum[j]=sum[w]+tmp[j];//更新杀敌数 
                } else if(num[w]+1==num[j]) { //节点一样
                    if(sum[w]>sum[path[j]]) { //杀敌人数较多
                        path[j]=w;//记录上一个节点编号
                        sum[j]=sum[w]+tmp[j];//更新杀敌数
                    }
                }
            }
        }
    }
}
int main() {
    Init();
    int i;
    for(i=0; i<Nv; i++) {
        path[i]=start;
    }
    Dijkstra(start);
    int road[MaxVex]= {0};
    int t=0,r=destination;
    while(r!=start) {
        road[t++]=r;
        r=path[r];
    }
    road[t]=start;
    for(i=t; i>=0; i--) {
        printf("%s",s[road[i]]);
        if(i!=0)
            printf("->");
    }
    printf("\n");
    printf("%d %d %d",cnt[destination],G[start][destination],sum[destination]);
    return 0;
}

 

posted @ 2020-03-21 20:12  跃鱼  阅读(615)  评论(0编辑  收藏  举报