zoukankan      html  css  js  c++  java
  • UVA 10269 Adventure of Super Mario

    看了这里 http://blog.csdn.net/acm_cxlove/article/details/8679230的分析之后自己又按照自己的模板写了一遍,算是对spfa又加深了一步认识(以前真是只会用,没想太多)。

    又来当一次搬运工,一点点进步。

    题意是这样的:A个村庄,B个城堡,共有K次穿越的机会,且不能经过城堡或者穿越距离必须不超过L,否则必须停下来,当然,不能再道路中间停下来。

    按照大大的思路是这样做的:对于每出队的一个结点u,均有两种方式继续走下去,一中是使用一次穿越,另一种是不使用。这样对于使用穿越的情况,必须考虑所有满足d[u][v]<=L的点v,然后dp[v][k+1] = min(dp[v][k+1],dp[u][k])转移方程,其中dp[u][k]表示从起点A+B走到u使用k次穿越经过的最小距离;对于不使用穿越的情况就和普通spfa一样转移。

    然后怎样判断由一个节点到另一个节点能够满足d[u][v]<=L呢,这中间会涉及到城堡不能穿越,可以求出使用spfa求出(i,j)之间的最短距离,对于j是城堡的时候就不把j入队,这样中间有城堡的两个节点d[i][j]是不能直接穿越的,也就是d[i][j] == inf.

    然后下面是我写的代码:

    (思路也可以去原po那里看)

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <climits>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <cmath>
      7 #include <vector>
      8 #include <queue>
      9 #include <algorithm>
     10 #define esp 1e-6
     11 #define pb push_back
     12 #define in  freopen("in.txt", "r", stdin);
     13 #define out freopen("out.txt", "w", stdout);
     14 #define print(a) printf("%d
    ",(a));
     15 #define bug puts("********))))))");
     16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
     17 #define inf 0x3f3f3f3f
     18 using namespace std;
     19 typedef long long  LL;
     20 typedef vector<int> VI;
     21 typedef vector<int>:: iterator IT;
     22 #define N 2000
     23 #define INF 200000
     24 struct EDGE
     25 {
     26     int i, c;
     27     EDGE *ani,*next;
     28 }   *Edge[N], E[INF];
     29 int d[N][N], inq[N], dp[N][20];
     30 int cnt, A, B, M, L, K;
     31 void add(int i, int j, int c, EDGE &e1, EDGE &e2)
     32 {
     33     e1.i = j, e1.c = c, e1.ani = &e2, e1.next = Edge[i], Edge[i] = &e1;
     34     e2.i = i, e2.c = c, e2.ani = &e1, e2.next = Edge[j], Edge[j] = &e2;
     35     cnt += 2;
     36 }
     37 void init(void)
     38 {
     39     cnt = 0;
     40     memset(Edge, 0, sizeof(Edge));
     41 //    memset(d, 0x0f, sizeof(d));
     42 }
     43 void preprocess(void)
     44 {
     45     memset(d, 0x3f, sizeof(d));
     46     for(int i = 1; i <= A + B; i++)
     47     {
     48         queue<int> q;
     49         memset(inq, 0, sizeof(inq));
     50         inq[i] = 1;
     51         d[i][i] = 0;
     52         q.push(i);
     53         while(!q.empty())
     54         {
     55             int u = q.front();
     56             int v;
     57             q.pop();
     58             inq[u] = 0;
     59             for(EDGE * p = Edge[u]; p; p = p->next)
     60                 if(d[i][v = p->i] > d[i][u] + p->c)
     61                 {
     62                     if(d[i][v] = d[i][u] + p->c, v <= A && !inq[v])
     63                         inq[v] = 1, q.push(v);
     64                 }
     65         }
     66     }
     67 }
     68 void spfa(int s, int end)
     69 {
     70     memset(dp, 0x3f, sizeof(dp));
     71     memset(inq, 0, sizeof(inq));
     72     queue<int> q;
     73     inq[s] = 1;
     74     dp[s][0] = 0;
     75     q.push(s);
     76     while(!q.empty())
     77     {
     78         int u = q.front(), v;
     79         q.pop();
     80         inq[u] = 0;
     81         for(EDGE *p = Edge[u]; p; p = p->next)
     82             for(int k = 0; k <= K; k++)
     83                 if(dp[u][k] < inf)
     84                 {
     85                     if(dp[v = p->i][k] > dp[u][k] + p->c)
     86                         if(dp[v][k] = dp[u][k] + p->c, !inq[v])
     87                             inq[v] = 1, q.push(v);
     88                     if(k - K)
     89                     {
     90                         for(v = 1; v <= A + B; v++)
     91 //                        if(dp[u][k] < inf)
     92                             if(d[u][v] <= L && dp[u][k] < dp[v][k+1])
     93                                 if(dp[v][k+1] = dp[u][k], !inq[v])
     94                                     inq[v] = 1, q.push(v);
     95                     }
     96                 }
     97     }
     98 }
     99 int main(void)
    100 {
    101 
    102     int T;
    103     for(int t = scanf("%d", &T); t <= T; t++)
    104     {
    105         init();
    106         scanf("%d%d%d%d%d", &A, &B, &M, &L, &K);
    107         for(int i = 1; i <= M; i++)
    108         {
    109             int u, v, w;
    110             scanf("%d%d%d", &u, &v, &w);
    111             add(u, v, w, E[cnt], E[cnt + 1]);
    112         }
    113         preprocess();
    114         spfa(A+B, 1);
    115         int ans = inf;
    116         for(int k = 0; k <= K; k++)
    117             ans = min(dp[1][k], ans);
    118         printf("%d
    ", ans);
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    Java并发之同步原语
    Iterator与ListIterator的区别
    java集合之深入分析ArrayList
    深入分析HashMap
    ssm项目,web容器无法初始化项目
    疯狂java学习笔记
    Delphi 转载:图形的移动、交错、雨滴状、百页窗、积木堆叠等显现方式
    Delphi 转载:Delphi 如何GET/POST 调用HTTP请求
    Delphi 界面和组件背景透明相关方法
    Delphi 把Form界面设置有弧度的矩形
  • 原文地址:https://www.cnblogs.com/rootial/p/SPFA-DP.html
Copyright © 2011-2022 走看看