• ACM/ICPC 之 最短路径-dijkstra范例(ZOJ2750-POJ1135(ZOJ1298))


    最短路经典算法-dijkstra范例(两道),第一道是裸的dijkstra,第二道需要枚举所有边已找到可能的情况。


    ZOJ2750-Idiomatic Phrases Game

      题意:见Code

      题解:dijkstra算法需要理解的是松弛操作,这一点掌握好了,其他的代码书写则有点类似于Prim算法,易于掌握。

         本题需要记录每一个成语的前4个字符和后4个字符以记录成语的第一个字和最后一个字,博主省略了建图的过程,直接重载了Idiom结构体的“==”运算符,在dijkstra也直接使用了该判断,经过分析可以知道这种算法和利用邻接矩阵建图后再进行dijkstra的算法时间度基本一致O(n^2),因此权当简化代码也好。

     1 //成语接龙-dijkstra
     2 //求从第一个成语道最后一个成语最短耗时(第一个列数据为T,表示需要耗时T后才能接龙下一个成语)
     3 //Time:50Ms    Memory:292K
     4 #include<iostream>
     5 #include<cstring>
     6 #include<cstdio>
     7 #include<vector>
     8 #include<algorithm>
     9 using namespace std;
    10 
    11 #define MAX 1001
    12 #define INF 0x3f3f3f3f
    13 
    14 struct Idiom {
    15     int time;
    16     char pre[5], rear[5];
    17     friend bool operator == (Idiom id1, Idiom id2) { return !strcmp(id1.rear, id2.pre); }
    18 }idiom[MAX];
    19 
    20 int n;
    21 int d[MAX], mintime;    //mintime:最短路耗时
    22 bool v[MAX];
    23 
    24 void dijkstra()
    25 {
    26     memset(v, false, sizeof(v));
    27     memset(d, INF, sizeof(d));
    28     v[0] = true;
    29     mintime = -1;    //默认失败
    30     for (int i = 1; i < n; i++)
    31     {
    32         if (idiom[0] == idiom[i])
    33             d[i] = idiom[0].time;
    34     }
    35     for (int i = 1; i < n; i++)
    36     {
    37         int mind = INF;
    38         int k;
    39         for (int j = 1; j < n;j++)
    40         {
    41             if (!v[j] && mind > d[j])
    42             {
    43                 mind = d[j];
    44                 k = j;
    45             }
    46         }
    47 
    48         if (mind == INF) return;    //失败
    49         if (k == n - 1) {    //成功
    50             mintime = d[k];
    51             return;
    52         }
    53         v[k] = true;
    54         for (int j = 1; j < n; j++)
    55             if (!v[j] && idiom[k] == idiom[j]) d[j] = min(d[k] + idiom[k].time, d[j]);
    56     }
    57 }
    58 
    59 int main()
    60 {
    61     while (scanf("%d", &n), n)
    62     {
    63         char str[25];
    64         for (int i = 0; i < n; i++)
    65         {
    66             scanf("%d%s", &idiom[i].time, str);
    67             int len = strlen(str);
    68             for (int j = 0; j < 4; j++)
    69             {
    70                 idiom[i].pre[j] = str[j];
    71                 idiom[i].rear[j] = str[len - 4 + j];
    72             }
    73             idiom[i].pre[4] = idiom[i].rear[4] = '';
    74         }
    75 
    76         dijkstra();
    77         printf("%d
    ", mintime);
    78     }
    79 
    80     return 0;
    81 }

    POJ1135(ZOJ1298)-Domino Effect

      题意及题解:见Code注释部分

     1 //求从1开始倒下的多米诺骨牌最后倒下的时间及在何处倒下(在两个关键牌中间倒下则输出两个关键牌)
     2 //dijkstra计算最短路,而后枚举每一条边上的时间(不一定在最短路的最大时间点和次大时间点内),以计算最后倒下的时间
     3 //Time:32Ms    Memory:1176K
     4 #include<iostream>
     5 #include<cstring>
     6 #include<cstdio>
     7 #include<algorithm>
     8 using namespace std;
     9 
    10 #define MAX 505
    11 #define INF 0x3f3f3f3f
    12 
    13 int n, m;
    14 int map[MAX][MAX];    //如果MAX达10^4以上,考虑用邻接表
    15 int d[MAX];
    16 bool v[MAX];
    17 int pos;    //关键牌编号
    18 double maxtime;    //关键牌最后倒下的时间
    19 
    20 void dijkstra()
    21 {
    22     memset(v, false, sizeof(v));
    23     memset(d, 0, sizeof(d));
    24     pos = 1;    //默认
    25     maxtime = 0;
    26     v[1] = true;
    27     for (int i = 2; i <= n; i++)
    28         d[i] = map[i][1];
    29     for (int i = 2; i <= n; i++)
    30     {
    31         int mind = INF;
    32         int k = 0;
    33         for (int j = 2; j <= n; j++)
    34         {
    35             if (!v[j] && mind > d[j])
    36             {
    37                 mind = d[j];
    38                 k = j;
    39             }
    40         }
    41         
    42         maxtime = mind;
    43         pos = k;
    44         v[k] = true;
    45         for (int j = 2; j <= n; j++)    //松弛
    46             if (!v[j]) d[j] = min(d[k] + map[k][j], d[j]);
    47     }
    48     
    49 }
    50 int main()
    51 {
    52     int cas = 0;
    53     while (scanf("%d%d", &n, &m), n || m)
    54     {
    55         memset(map, INF, sizeof(map));
    56         for (int i = 0; i < m; i++)
    57         {
    58             int u, v, w;
    59             scanf("%d%d%d", &u, &v, &w);
    60             map[u][v] = map[v][u] = w;
    61         }
    62         dijkstra();
    63         
    64         printf("System #%d
    ", ++cas);
    65         bool flag = false;    //存在关键牌外的牌倒下时间更多的情况
    66         int pos1, pos2;
    67         for (int i = 1; i <= n; i++)
    68             for (int j = i + 1; j <= n; j++)
    69             {
    70                 if (map[i][j] != INF && (d[i] + d[j] + map[i][j]) / 2.0 > maxtime)
    71                 {
    72                     maxtime = (d[i] + d[j] + map[i][j]) / 2.0;
    73                     pos1 = i;    pos2 = j;
    74                     flag = true;
    75                 }
    76             }
    77     
    78         if (flag)
    79             printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.
    
    ", maxtime, pos1, pos2);
    80         else printf("The last domino falls after %.1f seconds, at key domino %d.
    
    ", maxtime, pos);
    81     }
    82     return 0;
    83 }
    他坐在湖边,望向天空,她坐在对岸,盯着湖面
  • 相关阅读:
    CSRF攻击原理
    大前端
    尊敬自己,才能拥有改变的力量
    重温尼采语录 序章
    人生的弹性 -- 观《聚宝盆》有感
    求学梦
    爱国情怀
    雾中见我
    找东西
    走在路上的感悟
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5392465.html
Copyright © 2020-2023  润新知