zoukankan      html  css  js  c++  java
  • 城市来往最短路线

    书里面的一道题,记录一下代码。

    原题大概是这么个样子:如下图所示表示的是从城市A到城市H的交通图。从图中可以看出,从城市A到城市H要经过若干个城市。现要找出一条经过城市最少的一条路线。

    【算法分析】

    看到这图很容易想到用邻接距阵来存储图中各节点的边的关系,1表示能走,0表示不能走。

    首先想到的是用队列的思想。a数组是存储扩展结点的队列,a[i]记录经过的城市,b[i]记录前趋城市,这样就可以倒推出最短线路。具体过程如下:

    (1) 将城市A入队,队首为0、队尾为1。

    (2)将队首所指的城市所有可直通的城市入队(如果这个城市在队列中出现过就不入队,可用一布尔数组s[i]来判断),将入队城市的前趋城市保存在b[i]中。然后将队首加1,得到新的队首城市。重复以上步骤,直到搜到城市H时,搜索结束。利用b[i]可倒推出最少城市线路。

    下面稍微细化一下题设:

    输入n和e表示有n个城市,城市之间的连线有e条。然后输入e行,每行两个整数x和y表示城市x和y之间有边链接。

    接着输入s和d表示出发点和目的点。

    输出从s到d之间的最短路径(边的数量最少)以及路径长度 。

    用于测试的输入数据:

    8 12
    A B
    A F
    A D
    A C
    B F
    C D
    C E
    D G
    E G
    E H
    F H
    G H
    A H

    代码:

     1 #include <stdio.h>
     2 
     3 #define maxN 1005
     4 #define maxE 5005
     5 
     6 struct obj
     7 {
     8     int no,pre;
     9 };
    10 
    11 int n,e;//无向图的n个顶点,e条边(顶点编号:1~n)
    12 int p[maxN][maxN]={0};//邻接矩阵,无向图中各条边的数据   
    13 int begin,end;//出发点、终止点
    14 struct obj a[maxN];//BFS队列
    15 int head,tril;//队列的头、尾
    16 int check[maxN]={0};//check[i]==0表示第i个顶点未曾入队
    17 int flag=-1;//尚未搜索到终止点
    18 
    19 void BFS();
    20 void print();
    21 
    22 int main(int argc, char *argv[])
    23 {
    24     //freopen("data.txt","r",stdin);
    25     int i,x,y;
    26     char xx,yy;
    27     scanf("%d%d",&n,&e);getchar();
    28     for(i=0;i<e;i++)
    29     {
    30         scanf("%c %c",&xx,&yy);getchar();
    31         x=xx-'A'+1;  y=yy-'A'+1;
    32         p[x-1][y-1]=1;
    33         p[y-1][x-1]=1;
    34     }
    35     scanf("%c %c",&xx,&yy);
    36     begin=xx-'A'+1;  end=yy-'A'+1;
    37     begin--;
    38     end--;
    39     BFS();
    40     if(flag==1) print();
    41     else printf("no answer!
    ");
    42     return 0;
    43 }
    44 void BFS()
    45 {
    46     struct obj temp;
    47     int j;
    48     head=0;//初始化队列
    49     tril=0;//初始化队列
    50 
    51     a[tril].no=begin;//出发点入队
    52     a[tril].pre=-1;//出发点不考虑前驱节点
    53     check[begin]=1;//标记出发点已经入队
    54 
    55     if(begin==end)
    56     {
    57         flag=1;
    58         return ;//出发点和终止点相同,可以直接返回了。
    59     }
    60 
    61     while(tril-head+1>0)//当队列不为空时继续搜过
    62     {
    63         temp=a[head];
    64          for(j=0;j<maxN;j++)//寻找temp节点的相邻节点,把相邻节点入队
    65         {
    66             if(p[temp.no][j]==1&&check[j]==0)//发现相邻节点j而且相邻节点j尚未入过队
    67             {
    68                 tril++;
    69                 a[tril].no=j;//相邻节点j入队
    70                 a[tril].pre=head;//相邻节点j的上一个节点(也就是temp节点)在队列当中的下标
    71                 check[j]=1;
    72                 if(j==end)
    73                 {
    74                     flag=1;//已经找到了终点end
    75                     break;
    76                 }
    77             }
    78         }
    79         head++;//队头出队
    80         if(flag==1)
    81         {
    82             break;
    83         }
    84     }
    85 }
    86 void print()
    87 {
    88     int i;
    89     for(i=tril;i>=0;)
    90     {
    91         //printf("%d ",a[i].no+1);//输出节点编号(编号1~n)
    92         printf("%c ",a[i].no+'A'); 
    93         i=a[i].pre;
    94     }
    95     printf("
    ");
    96 }

    样例代码2:

      1 #include<stdio.h>
      2 #include<queue>
      3 #include<iostream>
      4 using namespace std;
      5 
      6 #define maxN 1005
      7 #define maxE 5005
      8 
      9 struct obj
     10 {
     11     int no,pre;
     12 };
     13 
     14 int n,e;//无向图的n个顶点,e条边(顶点编号:1~n)
     15 int p[maxN][maxN]={0};//邻接矩阵,无向图中各条边的数据   
     16 int begin,end;//出发点、终止点
     17 queue<obj> q;//BFS队列
     18 int s[maxN]={0};//用于记录出发点到目的点的路径。s[i]=k表节点i的前驱是节点k。 
     19 int check[maxN]={0};//check[i]==0表示第i个顶点未曾入队
     20 int flag=-1;//尚未搜索到终止点
     21 
     22 void BFS();
     23 void print();
     24 
     25 int main()
     26 {
     27     freopen("data.txt","r",stdin);
     28     int i,x,y;
     29     char xx,yy;
     30     scanf("%d%d",&n,&e);getchar();
     31     for(i=0;i<e;i++)
     32     {
     33         scanf("%c %c",&xx,&yy);getchar();
     34         /*x=xx-'A'+1;  y=yy-'A'+1;
     35         p[x-1][y-1]=1;
     36         p[y-1][x-1]=1;*/
     37         x=xx-'A'; y=yy-'A';
     38         p[x][y]=1;
     39         p[y][x]=1;
     40     }
     41     scanf("%c %c",&xx,&yy);
     42     /*begin=xx-'A'+1;  end=yy-'A'+1;
     43     begin--;
     44     end--;*/
     45     begin=xx-'A';  end=yy-'A';
     46     
     47     BFS();
     48     if(flag==1) print();
     49     else printf("no answer!
    ");
     50     return 0;
     51 }
     52 void BFS()
     53 {
     54     struct obj temp,temp2;
     55     int j;
     56 
     57     temp.no=begin;//出发点入队
     58     temp.pre=-1;//出发点不考虑前驱节点
     59     q.push(temp);
     60     check[begin]=1;//标记出发点已经入队
     61     s[begin]=-1;
     62     
     63     if(begin==end)
     64     {
     65         flag=1;
     66         return ;//出发点和终止点相同,可以直接返回了。
     67     }
     68 
     69     while(!q.empty())//当队列不为空时继续搜过
     70     {
     71         temp=q.front();
     72          for(j=0;j<maxN;j++)//寻找temp节点的相邻节点,把相邻节点入队
     73         {
     74             if(p[temp.no][j]==1&&check[j]==0)//发现相邻节点j而且相邻节点j尚未入过队
     75             {
     76                 temp2.no=j;
     77                 temp2.pre=temp.no;
     78                 q.push(temp2);
     79                 check[j]=1;
     80                 s[j]=temp.no;
     81                 
     82                 if(j==end)
     83                 {
     84                     flag=1;//已经找到了终点end
     85                     break;
     86                 }
     87             }
     88         }
     89         q.pop();//队头出队
     90         if(flag==1)
     91         {
     92             break;
     93         }
     94     }
     95 }
     96 void print()
     97 {
     98     int i;
     99     printf("%c ",end+'A');
    100     for(i=end;i!=begin;)
    101     {
    102         //printf("%d ",a[i].no+1);//输出节点编号(编号1~n)
    103         printf("%c ",s[i]+'A'); 
    104         i=s[i];
    105     }
    106     printf("
    ");
    107 }
  • 相关阅读:
    ASP.NET网页动态添加数据行
    动态生成自定义控件ascx如何给ascx传值
    读取txt文件将文本行组合成特定格式
    怎样对文本文件内的文本行排序
    动态变更Repeater控件HeaderTemplate列名
    减少代码冗余,封装你的程序
    在Repeater控件的OnItemDataBound获取数据源记录总数
    查看服务器系统资源(cpu,内容)利用率前几位的进程的方法
    Nginx反向代理+缓存开启+url重写+负载均衡(带健康探测)的部署记录
    gerrit代码简单备份方案分享
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/7227662.html
Copyright © 2011-2022 走看看