hdu 4179 Difficult Routes (SP)
坑了我一个晚上的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\n", ans); 97 else puts("None"); 98 } 99 return 0; 100 }
再搞搞几何就得开图论来练了!不然对于这种SB题目都毫无自己做错的意识,相当蛋疼的感觉。。_(:з」∠)_
——written by Lyon