• ACM/ICPC 之 最短路-Floyd+SPFA(BFS)+DP(ZOJ1232)


    这是一道非常好的题目,融合了很多知识点。


    ZOJ1232-Adventrue of Super Mario

      这一题折磨我挺长时间的,不过最后做出来非常开心啊,哇咔咔咔

      题意就不累述了,注释有写,难点在于状态转移方程的确立和SPFA的过程

      1 //最短路:Floyd+SPFA(BFS)+DP
      2 //Time:20Ms    Memory:336K
      3 //题目很好,数据较弱,网上部分代码有些问题却能够A掉
      4 //题意:超级马里奥要从A+B处背着公主以最短路程到达1处,其中1-A是村庄,剩下的是城堡
      5 //        有可使用K次可飞过L长的靴子(每次都以结点开始或结束),求最短路长
      6 //首先需要得到任意两点之间的最短路-Floyd较为简便(10^5次操作也能接受)
      7 //其次需要利用BFS从A+B处开始遍历并进行状态转移-BFS+DP
      8 //构造状态:DP[i][k]:从i到A+B经过k次瞬移得到的最短路
      9 //状态转移方程:
     10 //能够从x瞬移到y:dp[x][k] = min(dp[x][k], dp[y][k - 1], dp[y][k] + d[x][y])
     11 //不能从x瞬移到y:dp[x][k] = min(dp[x][k], dp[y][k] + d[x][y])
     12 #include<iostream>
     13 #include<cstring>
     14 #include<cstdio>
     15 #include<algorithm>
     16 #include<queue>
     17 #include<vector>
     18 using namespace std;
     19 
     20 #define INF 0x3f3f3f3f
     21 #define MAX 105
     22 
     23 vector<int> e[MAX];    //邻接表
     24 int A, B, M, L, K;
     25 int d[MAX][MAX];    //distance
     26 bool fly[MAX][MAX];    //能否瞬移
     27 int vis[MAX];
     28 int dp[MAX][12];    //dp[i][k]:从i到A+B经过k次瞬移得到的最短路
     29 
     30 void floyd(int N)
     31 {
     32     for (int i = 1; i <= N; i++)
     33         d[i][i] = 0;
     34     for (int k = 1; k <= N; k++)
     35         for (int i = 1; i <= N; i++)
     36             for (int j = 1; j <= N; j++)
     37                 if (d[i][j] > d[i][k] + d[k][j])
     38                 {
     39                     d[i][j] = d[i][k] + d[k][j];
     40                     if (k <= A && d[i][j] <= L)
     41                     {
     42                         fly[i][j] = true;
     43                         e[i].push_back(j);
     44                     }
     45                 }
     46 }
     47 
     48 int main()
     49 {
     50     //freopen("in.txt", "r", stdin);
     51     //freopen("out-2.txt", "w", stdout);
     52     int T;
     53     scanf("%d", &T);
     54     while (T--) {
     55         memset(d, INF, sizeof(d));
     56         memset(fly, false, sizeof(fly));
     57         memset(e, 0, sizeof(e));
     58         scanf("%d%d%d%d%d", &A, &B, &M, &L, &K);
     59         while (M--) {
     60             int u, v, w;
     61             scanf("%d%d%d", &u, &v, &w);
     62             d[v][u] = d[u][v] = w;
     63             e[v].push_back(u);
     64             e[u].push_back(v);
     65             if (w <= L)    fly[u][v] = fly[v][u] = true;
     66         }
     67 
     68         floyd(A + B);
     69         //类似SPFA的过程(BFS)
     70         memset(dp, INF, sizeof(dp));
     71         for (int i = 1; i <= K; i++)
     72             dp[A + B][i] = 0;
     73         for (int i = 1; i <= A + B; i++)
     74             dp[i][0] = d[i][A + B];
     75         for (int k = 1; k <= K; k++)
     76         {
     77             memset(vis, false, sizeof(vis));
     78             queue<int> q;
     79             q.push(A + B);    //从A+B开始遍历
     80             vis[A + B] = true;
     81             while (!q.empty()) {
     82                 int cur = q.front();
     83                 q.pop();
     84                 for (int i = 0; i < e[cur].size(); i++)
     85                 {
     86                     int u = e[cur][i];
     87                     int tmp = dp[u][k];
     88                     //状态转移
     89                     if (fly[u][cur])    //可瞬移
     90                         dp[u][k] = min(dp[u][k], dp[cur][k - 1]);
     91                     dp[u][k] = min(dp[u][k], dp[cur][k] + d[cur][u]);
     92                     //需要转移状态的条件 - 没有访问过 or 最短路长变更
     93                     if (!vis[u] || tmp != dp[u][k])
     94                         q.push(u);
     95                     vis[u] = true;
     96                 }
     97             }
     98         }
     99         printf("%d
    ", dp[1][K]);
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    JAVA软件开发职责
    Redis主从复制配置
    VirtualBox安装Ubuntu教程
    分段锁——ConcurrentHashMap
    阻塞队列BlockingQueue用法
    阻塞队列--LinkedBlockingQueue
    MySQL百万级数据库优化方案
    获取主机的对外ip
    联通沃云开启80端口
    Nginx 正则匹配
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5452439.html
Copyright © 2020-2023  润新知