hdu 4179 Difficult Routes (SP)

Problem - 4179

  坑了我一个晚上的SP题。

  题意是,给出若干空间中的点,给出其中某些点之间是有直线线段路径相连的。要求求出一条从s开始到t结束的路径,它的难度是d。难度的计算是空间线段两点的高度差乘以100再除以投影到xOy平面上线段的长度。难度是d的路径的定义是路径中,经过的线段的难度最大是d。

  其实比较容易可以想到的是枚举难度最大的线段的,同时构建难度小于等于给定值的正图和反图。正图是用来求出起点s到各个顶点的最短距离,因为是有向图,所以求出t到各个顶点的最短距离是要用到反图来求的。然后就将两条路径拼接到被枚举的线段上。

  中间错的好多的是,写之前还想到要用反图求t到各个顶点的最短距离,结果写的时候就忘记了,最后多得队友ly的提醒!然后就是比较SB的一个行为了。明明就是直接拼接上去就好了,结果我想太多,没有考虑到我的图是有向图,搞多了两个比较,于是就狠狠的被坑了一个晚上了!!!_(:з」∠)_

代码如下:

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cstring>
  6 
  7 using namespace std;
  8 
  9 const int N = 11111;
 10 const int M = 55555;
 11 int eh[2][N], ec[2];
 12 struct Edge {
 13     int id, nx, df;
 14     double l;
 15     Edge() {}
 16     Edge(int id, int nx, int df, double l) : id(id), nx(nx), df(df), l(l) {}
 17 } edge[2][M << 1];
 18 
 19 inline void init() {
 20     memset(eh, -1, sizeof(eh));
 21     memset(ec, 0, sizeof(ec));
 22 }
 23 
 24 inline void addedge(int u, int v, int df, double l, int id) {
 25     edge[id][ec[id]] = Edge(v, eh[id][u], df, l);
 26     eh[id][u] = ec[id]++;
 27 }
 28 
 29 int x[N], y[N], z[N];
 30 template<class T> inline T sqr(T a) { return a * a;}
 31 int st[M << 1], ed[M << 1];
 32 
 33 inline int getdf(int a, int b) {
 34     if (z[a] >= z[b]) return 0;
 35     double len = sqrt(sqr((double) x[a] - x[b]) + sqr((double) y[a] - y[b]));
 36     return (int) floor(100.0 * (z[b] - z[a]) / len);
 37 }
 38 
 39 inline double getdis(int a , int b) { return sqrt(sqr((double) x[a] - x[b]) + sqr((double) y[a] - y[b]) + sqr((double) z[a] - z[b]));}
 40 const double FINF = 1e50;
 41 double dis[2][N];
 42 int q[M << 1];
 43 bool vis[N];
 44 
 45 void spfa(int s, int id) {
 46     for (int i = 0; i < N; i++) dis[id][i] = FINF;
 47     int qh, qt;
 48     qh = qt = 0;
 49     dis[id][s] = 0;
 50     q[qt++] = s;
 51     vis[s] = true;
 52     while (qh < qt) {
 53         int cur = q[qh++];
 54         vis[cur] = false;
 55         for (int i = eh[id][cur]; ~i; i = edge[id][i].nx) {
 56             if (dis[id][edge[id][i].id] > dis[id][cur] + edge[id][i].l) {
 57                 dis[id][edge[id][i].id] = dis[id][cur] + edge[id][i].l;
 58                 if (!vis[edge[id][i].id]) q[qt++] = edge[id][i].id, vis[edge[id][i].id] = true;
 59             }
 60         }
 61     }
 62 }
 63 
 64 int main() {
 65 //    freopen("in", "r", stdin);
 66     int n, m;
 67     while (~scanf("%d%d", &n, &m) && (n || m)) {
 68         for (int i = 1; i <= n; i++) scanf("%d%d%d", &x[i], &y[i], &z[i]);
 69         for (int i = 0; i < m; i++) scanf("%d%d", &st[i], &ed[i]);
 70         int A, B, D;
 71         scanf("%d%d%d", &A, &B, &D);
 72         init();
 73         for (int i = 0; i < m; i++) {
 74             double tmp = getdis(st[i], ed[i]);
 75             int df = getdf(st[i], ed[i]);
 76             if (df <= D) {
 77                 addedge(st[i], ed[i], df, tmp, 0);
 78                 addedge(ed[i], st[i], df, tmp, 1);
 79             }
 80             df = getdf(ed[i], st[i]);
 81             if (df <= D) {
 82                 addedge(ed[i], st[i], df, tmp, 0);
 83                 addedge(st[i], ed[i], df, tmp, 1);
 84             }
 85         }
 86         spfa(A, 0);
 87         spfa(B, 1);
 88 //        for (int i = 1; i <= n; i++) cout << dis[0][i] << ' '; cout << endl;
 89 //        for (int i = 1; i <= n; i++) cout << dis[1][i] << ' '; cout << endl;
 90         double ans = FINF;
 91         for (int i = 1; i <= n; i++) {
 92             for (int t = eh[0][i]; ~t; t = edge[0][t].nx) {
 93                 if (edge[0][t].df == D) ans = min(ans, dis[0][i] + edge[0][t].l + dis[1][edge[0][t].id]);
 94             }
 95         }
 96         if (ans < FINF) printf("%.1f
", ans);
 97         else puts("None");
 98     }
 99     return 0;
100 }
View Code

  再搞搞几何就得开图论来练了!不然对于这种SB题目都毫无自己做错的意识,相当蛋疼的感觉。。_(:з」∠)_

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4179_Lyon.html