UVa10269 Adventure of Super Mario

不错的最短路题.一开始没想到如何处理 "Mario NEVER super runs through a Castle" 这个条件,然后大力分类讨论.

在写了将近70行的状态扩展后,我放弃了.

实际上,这题没有这么麻烦.这个条件限制只用在floyd预处理的时候就可以解决了.

具体来说, 在floyd的时候,限制中转点为乡村

        for(int k = 1; k <= A; k++)
            for(int i = 1; i <= (A + B); i++)
                for(int j = 1; j <= (A + B); j++)

 根据算法的性质, 这样所有路径除起点, 终点之外的点就都在乡村了.

用了这个非常妙的做法以后, 就不难写出状态的扩展了.

这里用的是dijkstra

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <queue>
 7 using namespace std;
 8 const int MAXN = 1e2 + 20;
 9 const int INF = 0x3f3f3f3f;
10 
11 int A, B, M, L, K;
12 int d[MAXN][MAXN], f[MAXN][12];
13 bool vis[MAXN][12];
14 
15 struct edge
16 {
17     int to, cost;
18 };vector<edge> g[MAXN];
19 struct state
20 {
21     int pos, time, k;
22     state(int u = 0, int t = 0, int k = 0) :
23     pos(u), time(t), k(k) {}
24     bool operator >(const state &rhs) const{
25         return time > rhs.time;
26     }
27 };
28 
29 void init()
30 {
31     memset(d, 0x3f, sizeof(d));
32     memset(f, 0x3f, sizeof(f));
33     memset(vis, false, sizeof(vis));
34     for(int i = 1; i <= (A + B); i++) g[i].clear();
35 }
36 
37 void floyd()
38 {
39     for(int i = 1; i <= (A + B); i++) d[i][i] = 0;
40         for(int k = 1; k <= A; k++)
41             for(int i = 1; i <= (A + B); i++)
42                 for(int j = 1; j <= (A + B); j++)
43                     if(d[i][k] != INF && d[k][j] != INF)
44                         d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
45 }
46 
47 inline bool tension(const int &st, int &lg)
48 {
49     return st < lg ? (lg = st, true) : false;
50 }
51 
52 int bfs()
53 {
54     priority_queue<state, vector<state>, greater<state> > q;
55     f[(A + B)][0] = 0;
56     q.push(state((A + B), 0, 0));
57 
58     while(!q.empty())
59     {
60         state u = q.top(); q.pop();
61         if(u.pos == 1) return u.time;
62         if(vis[u.pos][u.k]) continue;
63         vis[u.pos][u.k] = true;
64         for(int i = 0; i < (int) g[u.pos].size(); i++)
65         {
66             edge &e = g[u.pos][i];
67             if(tension(u.time + e.cost, f[e.to][u.k]))
68                 q.push(state(e.to, f[e.to][u.k], u.k));
69         }
70 
71         if(u.k < K)
72         for(int i = 1; i <= (A + B); i++)
73             if(d[i][u.pos] <= L && tension(u.time + 0, f[i][u.k + 1]))
74                 q.push(state(i, f[i][u.k + 1], u.k + 1));
75     }
76     return rand();
77 }
78 
79 int main()
80 {
81     //freopen("10269.in", "r", stdin);
82     //freopen("10269.out", "w", stdout);
83     int T; cin>>T;
84     while(T--)
85     {
86         cin>>A>>B>>M>>L>>K;init();
87         for(int i = 1, u, v, c; i <= M; i++)
88         {
89             scanf("%d%d%d", &u, &v, &c);
90             d[u][v] = d[v][u] = c;
91             g[u].push_back((edge){v, c});
92             g[v].push_back((edge){u, c});
93         }
94         floyd();
95         printf("%d\n", bfs());
96     }
97     return 0;
98 }

 

posted @ 2018-06-20 09:15  俺是小程  阅读(179)  评论(0编辑  收藏  举报