该题的关键是题干最后一句:如果有不同的路线都是最短路,那么输出第一跳最短的路线。解决方法是把湖心小岛周围一圈的节点(即距离湖心小岛小于D的鳄鱼)看作起点,对这些起点依次调用无权最短路算法,找出路径最短(且相同)的那些起点,然后比较从湖心小岛到它们的距离,输出最小的距离所在的路径即可。
#include <iostream> #include <vector> #include <queue> #include <stack> #include <cmath> #define fuck cout << endl; using namespace std; struct Coordinate { int x; int y; }; bool operator==(Coordinate& a, Coordinate& b) { return a.x == b.x && a.y == b.y; } float DistanceOfPoints(const Coordinate& a, const Coordinate& b) { return sqrtf(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)); } void JudgePosition(const int& D, Coordinate* crocodile, const int& i, bool* isCloseToEdge, bool* isCloseToCenter) { // 靠近湖岸 if (crocodile[i].x >= 50 - D || crocodile[i].x <= -50 + D || crocodile[i].y >= 50 - D || crocodile[i].y <= -50 + D) { isCloseToEdge[i] = true; } else { isCloseToEdge[i] = false; } // 靠近湖心小岛 if ( sqrtf(pow(crocodile[i].x, 2) + pow(crocodile[i].y, 2)) <= 7.5 + D) { isCloseToCenter[i] = true; } else { isCloseToCenter[i] = false; } } bool IsCloseToEdge(const int& D, const Coordinate& crocodile) { return (crocodile.x >= 50 - D || crocodile.x <= -50 + D || crocodile.y >= 50 - D || crocodile.y <= -50 + D); } bool IsCloseToCenter(const int& D, const Coordinate& crocodile) { return (sqrtf(pow(crocodile.x, 2) + pow(crocodile.y, 2)) <= 7.5 + D); } vector<int> UnweightedShortestWay(const int& s, vector<vector<int> >& graph, vector<Coordinate>& crocodile) { Coordinate O; O.x = 0; O.y = 0; int minPath = 9999; int minFirstHeap = 9999; vector<int> bestPath; // 一共s个鳄鱼,s是湖心小岛,s+1是岸边 for (int i = 0; i < graph[s].size(); i++) { bool isInitialFind = true; float currentHeapDistance = DistanceOfPoints(O, crocodile[graph[s][i]]); vector<int> currentPath(s + 2, -1); vector<int> distance(s + 2, -1); distance[graph[s][i]] = 0; queue<int> nodeQueue; nodeQueue.push(graph[s][i]); while(!nodeQueue.empty()) { bool isFind = false; int lastNode = nodeQueue.front(); nodeQueue.pop(); for (int j = 0; j < graph[lastNode].size(); j++) { // graph[lastNode][j]是和lastNode相连的节点的编号 int currentNode = graph[lastNode][j]; if (distance[currentNode] == -1) { distance[currentNode] = distance[lastNode] + 1; currentPath[currentNode] = lastNode; if (currentNode == s + 1) { if (isInitialFind) { isInitialFind = false; //minPath = distance[currentNode]; } if (distance[currentNode] < minPath) { minPath = distance[currentNode]; minFirstHeap = currentHeapDistance; bestPath = currentPath; } else if (distance[currentNode] == minPath) { if (currentHeapDistance < minFirstHeap) { minFirstHeap = currentHeapDistance; bestPath = currentPath; } } } nodeQueue.push(currentNode); if (!isInitialFind) { isFind = true; break; } } } if (isFind) { break; } } } return bestPath; } int main() { int N; int D; scanf("%d %d", &N, &D); int nodeCount = N + 2; vector<vector<int> > graph(nodeCount); vector<Coordinate> crocodile(nodeCount); for (int i = 0; i < N; i++) { scanf("%d %d", &crocodile[i].x, &crocodile[i].y); } crocodile[N].x = 0; crocodile[N].y = 0; crocodile[N + 1].x = -1; crocodile[N + 1].y = -1; // 一共N个鳄鱼,N是湖心小岛,N+1是岸边 for (int i = 0; i < N; i++) { if (IsCloseToCenter(D, crocodile[i])) { graph[i].push_back(N); graph[N].push_back(i); } if (IsCloseToEdge(D, crocodile[i])) { graph[i].push_back(N + 1); graph[N + 1].push_back(i); } for (int j = i + 1; j < N; j++) { if (DistanceOfPoints(crocodile[i], crocodile[j]) <= D) { graph[i].push_back(j); graph[j].push_back(i); } } } // 如果湖心小岛和岸边距离小于D if (50 - 7.5 <= D) { graph[N].push_back(N + 1); graph[N + 1].push_back(N); printf("1\n"); return 0; } vector<vector<int> > path; vector<int> bestPath = UnweightedShortestWay(N, graph, crocodile); if (graph[N].empty() || graph[N + 1].empty()) { printf("0\n"); return 0; } int i = N + 1; int n = 0; stack<Coordinate> pathStack; while (bestPath[i] != -1) { i = bestPath[i]; pathStack.push(crocodile[i]); n++; } printf("%d\n", pathStack.size() + 1); while (!pathStack.empty()) { printf("%d %d\n", pathStack.top().x, pathStack.top().y); pathStack.pop(); } return 0; }
时间: 2024-10-18 08:59:55