建立一个图 用dijkstra求图的最短路 #include <cstdio> #include <cstdlib> #include <cmath> #include <cassert> #include <algorithm> using namespace std; #define MAX_VERTEX 500 //#define NIL -1 //#define NOT_NIL 1 //#define SOURCE 300 //#define DESTINATION 301 #define INF_DOUBLE 1e15 #define INF_INT 0x1fffffff struct coord_t { double x; double y; }; coord_t coords[MAX_VERTEX]; double edge_weight[MAX_VERTEX][MAX_VERTEX]; bool is_adjacence[MAX_VERTEX][MAX_VERTEX]; int real_vertexs; int island_vertexs; int bank_vertexs; int source, destination; double max_edge_weight; const double radius = 7.5; double dist(double x, double dx, double y, double dy) { return sqrt((x - dx) * (x - dx) + (y - dy) * (y - dy)); } bool is_equal(double a, double b) { return fabs(a - b) < 1e-15; } bool is_both_island_vertex(int v, int w) { assert(v < real_vertexs + island_vertexs + bank_vertexs); assert(w < real_vertexs + island_vertexs + bank_vertexs); return real_vertexs <= v && v < real_vertexs + island_vertexs && real_vertexs <= w && w < real_vertexs + island_vertexs; } bool is_both_bank_vertex(int v, int w) { assert(v < real_vertexs + island_vertexs + bank_vertexs); assert(w < real_vertexs + island_vertexs + bank_vertexs); return real_vertexs + island_vertexs <= v && real_vertexs + island_vertexs <= w; } void add_virtual_edges(); void scan_graph(); void init_global() { scan_graph(); source = -1; destination = -1; island_vertexs = 0; bank_vertexs = 0; add_virtual_edges(); int vertexs = real_vertexs + island_vertexs + bank_vertexs; for(int v=0; v<vertexs; ++v) { for(int w=0; w<vertexs; ++w) { if(is_both_island_vertex(v, w) || is_both_bank_vertex(v, w)) { edge_weight[v][w] = 0.0; is_adjacence[v][w] = true; } else { edge_weight[v][w] = dist(coords[v].x, coords[w].x, coords[v].y, coords[w].y); if(edge_weight[v][w] <= max_edge_weight) is_adjacence[v][w] = true; else is_adjacence[v][w] = false; } }//for w }//for v } void add_virtual_edges() { source = real_vertexs + island_vertexs; coords[source].x = -100.0; coords[source].x = -100.0; island_vertexs = 1; for(int v=0; v<real_vertexs; ++v) { double to_center = dist(0.0, coords[v].x, 0.0, coords[v].y); if(to_center - radius > max_edge_weight) continue; coords[real_vertexs + island_vertexs].x = coords[v].x * radius / to_center; coords[real_vertexs + island_vertexs].y = coords[v].y * radius / to_center; ++island_vertexs; } destination = real_vertexs + island_vertexs + bank_vertexs; coords[destination].x = 100.0; coords[destination].y = 100.0; bank_vertexs = 1; enum bank_t { up_bank, down_bank, left_bank, right_bank } bank; for(int v=0; v<real_vertexs; ++v) { assert(coords[v].x >= -50.0); assert(coords[v].x <= 50.0); assert(coords[v].y >= -50.0); assert(coords[v].y <= 50.0); double to_bank = 50.0 - coords[v].x; bank = right_bank; if(to_bank > coords[v].x + 50.0) { to_bank = coords[v].x + 50.0; bank = left_bank; } if(to_bank > 50.0 - coords[v].y) { to_bank = 50.0 - coords[v].y; bank = up_bank; } if(to_bank > coords[v].y + 50.0) { to_bank = coords[v].y + 50.0; bank = down_bank; } if(to_bank > max_edge_weight) continue; switch(bank) { case up_bank: coords[real_vertexs + island_vertexs + bank_vertexs].x = coords[v].x; coords[real_vertexs + island_vertexs + bank_vertexs].y = 50.0; break; case down_bank: coords[real_vertexs + island_vertexs + bank_vertexs].x = coords[v].x; coords[real_vertexs + island_vertexs + bank_vertexs].y = -50.0; break; case left_bank: coords[real_vertexs + island_vertexs + bank_vertexs].x = -50.0; coords[real_vertexs + island_vertexs + bank_vertexs].y = coords[v].y; break; case right_bank: coords[real_vertexs + island_vertexs + bank_vertexs].x = 50.0; coords[real_vertexs + island_vertexs + bank_vertexs].y = coords[v].y; break; default: assert(false); } ++bank_vertexs; } } void scan_graph() { if(scanf("%d%lf", ℜ_vertexs, &max_edge_weight) == EOF) exit(0); for(int v=0; v<real_vertexs; ++v) scanf("%lf%lf", &coords[v].x, &coords[v].y); } double dijkstra(int source, int destination, int &_lv) { if(source < 0 || destination < 0) return INF_DOUBLE; const int vertexs = real_vertexs + island_vertexs + bank_vertexs; double d[MAX_VERTEX]; fill(d, d + MAX_VERTEX, INF_DOUBLE); d[source] = 0.0; int lv[MAX_VERTEX]; fill(lv, lv + MAX_VERTEX, INF_INT); lv[source] = 0; bool is_discovered[MAX_VERTEX]; fill(is_discovered, is_discovered + MAX_VERTEX, false); for(int v=0; v<vertexs; ++v) { int min_d_vertex = -1; for(int w=0; w<vertexs; ++w) { if(is_discovered[w]) continue; if(min_d_vertex == -1) min_d_vertex = w; else if(d[min_d_vertex] > d[w]) min_d_vertex = w; else if(is_equal(d[min_d_vertex], d[w]) && lv[min_d_vertex] > lv[w]) min_d_vertex = w; } assert(min_d_vertex != -1); is_discovered[min_d_vertex] = true; for(int w=0; w<vertexs; ++w) { if(!is_adjacence[min_d_vertex][w]) continue; if(is_discovered[w]) continue; double new_d = d[min_d_vertex] + edge_weight[min_d_vertex][w]; int new_lv = lv[min_d_vertex] + 1; if(d[w] > new_d || (is_equal(d[w], new_d) && lv[w] > new_lv)) { d[w] = new_d; lv[w] = new_lv; } } } _lv = lv[destination] - 2; return d[destination]; } void solve() { //scan and build the graph init_global(); if(max_edge_weight >= 42.5) { printf("42.50 1/n"); return; } int lv = 0; double d = dijkstra(source, destination, lv); if(d < INF_DOUBLE) printf("%.2lf %d/n", d, lv); else printf("can't be saved/n"); } int main() { while(true) { solve(); } } /* 4 10 17 0 27 0 37 0 45 0 1 10 20 30 5 10 17 0 27 0 37 0 45 0 47 0 0 10 0 100 */