HDU 5636 Shortest Path

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5636

题解:

1、暴力枚举:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;

int n, m;
int a[11], b[11];

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < 3; i++) scanf("%d%d", a + i, b + i);
        LL ans = 0;
        int x, y;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d", &x, &y);
            //一条新路线都不走
            int tmp = abs(x - y);
        
            //只走一条
            for (int j = 0; j < 3; j++) {
                tmp = min(tmp, abs(x - a[j]) + abs(b[j] - y) + 1);
                tmp = min(tmp, abs(x - b[j]) + abs(a[j] - y) + 1);
            }

            //走两条
            for (int j = 0; j < 3; j++) {
                for (int k = 0; k < 3; k++) {
                    if (j == k) continue;
                    //x -> j开头 -> j结尾 -> k开头 -> k结尾 -> y
                    tmp = min(tmp, abs(x - a[j]) + abs(b[j] - a[k]) + abs(b[k] - y) + 2);
                    //x -> j开头 -> j结尾 -> k结尾 -> k开头 -> y
                    tmp = min(tmp, abs(x - a[j]) + abs(b[j] - b[k]) + abs(a[k] - y) + 2);
                    //x -> j结尾 -> j开头 -> k开头 -> k结尾 -> y
                    tmp = min(tmp, abs(x - b[j]) + abs(a[j] - a[k]) + abs(b[k] - y) + 2);
                    //x -> j结尾 -> j开头 -> k结尾 -> k开头 -> y
                    tmp = min(tmp, abs(x - b[j]) + abs(a[j] - b[k]) + abs(a[k] - y) + 2);
                }
            }

            //走三条
            for (int j = 0; j < 3; j++) {
                for (int k = 0; k < 3; k++) {
                    if (j == k) continue;
                    for (int w = 0; w < 3; w++) {
                        if (w == j || w == k) continue;
                        tmp = min(tmp, abs(x - a[j]) + abs(b[j] - a[k]) + abs(b[k] - a[w]) + abs(b[w] - y) + 3);
                        tmp = min(tmp, abs(x - a[j]) + abs(b[j] - a[k]) + abs(b[k] - b[w]) + abs(a[w] - y) + 3);
                        tmp = min(tmp, abs(x - a[j]) + abs(b[j] - b[k]) + abs(a[k] - a[w]) + abs(b[w] - y) + 3);
                        tmp = min(tmp, abs(x - a[j]) + abs(b[j] - b[k]) + abs(a[k] - b[w]) + abs(a[w] - y) + 3);

                        tmp = min(tmp, abs(x - b[j]) + abs(a[j] - a[k]) + abs(b[k] - a[w]) + abs(b[w] - y) + 3);
                        tmp = min(tmp, abs(x - b[j]) + abs(a[j] - a[k]) + abs(b[k] - b[w]) + abs(a[w] - y) + 3);
                        tmp = min(tmp, abs(x - b[j]) + abs(a[j] - b[k]) + abs(a[k] - a[w]) + abs(b[w] - y) + 3);
                        tmp = min(tmp, abs(x - b[j]) + abs(a[j] - b[k]) + abs(a[k] - b[w]) + abs(a[w] - y) + 3);
                    }
                }
            }
            ans += ((LL)i*tmp)%mod;
            ans %= mod;
        }
        printf("%lld
", ans);
    }
    return 0;
}
View Code

 2、floyd:

对三条新边对应的关键顶点重新建图,跑一遍floyd最短路,对于查询(xi,yi),我们枚举任意两个关键节点(aj,bj),求min(|xi-aj|+len+|bj-yi|),其中len表示新图里面aj到bj的最短距离。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 const int maxn = 1e5 + 10;
10 const int mod = 1e9 + 7;
11 const int INF = 0x3f3f3f3f;
12 
13 int n, m;
14 int a[11],mat[11][11];
15 
16 void init() {
17     memset(mat, 0x3f, sizeof(mat));
18     for (int i = 0; i < 11; i++) mat[i][i] = 0;
19 }
20 
21 int main() {
22     int tc;
23     scanf("%d", &tc);
24     while (tc--) {
25         init();
26         scanf("%d%d", &n, &m);
27         for (int i = 0; i < 3; i++) {
28             scanf("%d%d", a + i, a + i + 3);
29         }
30         //新图
31         for (int i = 0; i < 6; i++) {
32             for (int j = 0; j < 6; j++) {
33                 mat[i][j] = abs(a[i] - a[j]);
34             }
35         }
36         for (int i = 0; i < 3; i++) {
37             mat[i][i + 3] = mat[i + 3][i] = 1;
38         }
39         //floyd
40         for (int k = 0; k < 6; k++) {
41             for (int i = 0; i < 6; i++) {
42                 for (int j = 0; j < 6; j++) {
43                     mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]);
44                 }
45             }
46         }
47         LL ans = 0;
48         for (int i = 1; i <= m; i++) {
49             int x, y;
50             scanf("%d%d", &x, &y);
51             LL z = abs(x-y);
52             //枚举所有情况
53             for (int i = 0; i < 6; i++) {
54                 for (int j = 0; j < 6; j++) {
55                     int tmp = abs(x - a[i]) + mat[i][j] + abs(a[j] - y);
56                     z = min(z, (LL)tmp);
57                 }
58             }
59             ans += z*i;
60             ans %= mod;
61         }
62         printf("%lld
", ans);
63     }
64     return 0;
65 }
View Code
  
原文地址:https://www.cnblogs.com/fenice/p/5246309.html