ZOJ 1232 Adventure of Super Mario (Floyd + DP)

题意:有a个村庄,编号为1到a,有b个城堡,编号为a+1到a+b。现在超级玛丽在a+b处,他的家在1处。每条路是双向的,两端地点的编号以及路的长度都已给出。路的长度和通过所需时间相等。他有一双鞋子,可以使用k次,每次使用后最多可以跑过l的距离,且通过这段距离所需时间为0。使用鞋子时,必须从村庄或城堡开始,到村庄或者城堡结束。但是,城堡充满了陷阱,他如果中途遇见城堡,就必须停下来,且鞋子视为使用完了一次。问超级玛丽回家所需的最短时间。

思路:用floyd算法先处理出任意两点间的最短距离(不用鞋子时)。另用一个二维数组来维护两点之间是否允许用鞋子直接传送。当两点最短距离不大于l且中间不经过城堡时,数组值为真。

然后,进行dp。dp[i][k]表示从1到i用了k次鞋子时的最短时间(边是双向的,从1开始和从a+b开始是等价的)。

dp[i][k] = min(dp[j][k-1], dp[j][k])。当j到i不允许穿鞋子时,只有后面一项。最后dp[a+b][k]即为最终结果。

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define inf 0x3f3f3f3f
 5 #define maxn 105
 6 using namespace std;
 7 int a, b, m, l, tk;
 8 int d[maxn][maxn], ok[maxn][maxn], dp[maxn][12];
 9 void floyd()
10 {
11     for (int k = 1; k <= a + b; k++)
12         for (int i = 1; i <= a + b; i++)
13             for (int j = 1; j <= a + b; j++)
14                 if (d[i][j] > d[i][k] + d[k][j])
15                 {
16                     d[i][j] = d[i][k] + d[k][j];
17                     if (k <= a && d[i][j] <= l) ok[i][j] = ok[j][i] = 1;
18                 }
19 }
20 void run_dp()
21 {
22     for (int i = 1; i <= a + b; i++)
23         dp[i][0] = d[1][i];
24     for (int i = 0; i <= tk; i++)
25         dp[1][i] = 0;
26     for (int i = 2; i <= a + b; i++)
27         for (int k = 1; k <= tk; k++)
28         {
29             int tmin = inf;
30             for (int j = 1; j < i; j++)
31             {
32                 if (ok[j][i])
33                     tmin = min(tmin, dp[j][k-1]);
34                 tmin = min(tmin, dp[j][k] + d[j][i]);
35             }
36             dp[i][k] = tmin;
37         }
38 }
39 int main()
40 {
41     int t;
42     //freopen("data.in", "r", stdin);
43     scanf("%d", &t);
44     while (t--)
45     {
46         scanf("%d%d%d%d%d",&a,&b,&m,&l,&tk);
47         memset(d, 0x3f, sizeof(d));
48         memset(ok, 0, sizeof(ok));
49         while (m--)
50         {
51             int u, v, w;
52             scanf("%d%d%d",&u,&v,&w);
53             d[u][v] = d[v][u] = w;
54             if (w <= l) ok[u][v] = ok[v][u] = 1;
55         }
56         floyd();
57         run_dp();
58         printf("%d\n",dp[a+b][tk]);
59     }
60     return 0;
61 }

 

 

 

posted @ 2013-08-07 17:42  fenshen371  阅读(250)  评论(0编辑  收藏  举报