/* Subject: Contest submission for problem #3, file 3.cc */ /* koulchin@imail.EECS.Berkeley.EDU */ /* Thu Sep 18 13:22:43 PDT 2003 */ /*___CONTEST_SUBMISSION___ koulchin 3 */ // Maze // Estimated time: 1 hour // Starting time: 4:10pm // Ending time: // coding: 5:44pm, mostly due to gratuitous goofing off on my part, // debugging: 7:00pm. Had one major error: was not labeling things properly in BFS init // Actual time: 2:50 // An additional 30 minutes was spent ensuring the Borogove would always chose the shortest // path that began with the lowest room number after the last common room #include class LinkedList; class Vertex { public: LinkedList *edges; // adjacent vertices int label; int num; // number needed only because of requirement to take lowest numbered path0 Vertex *parent; // used in pathfinding }; class LinkedList { public: Vertex *v; int label; LinkedList *next; }; void Insert(Vertex *v, LinkedList **ll, int label); LinkedList* FindShortestPath(Vertex *src, Vertex *dst); void MarkDistances(Vertex *src); bool ComparePaths(Vertex *v1, Vertex *v2); int vertexCount; // global because it's used by ComparePaths int main() { int n, j, k; Vertex *allVertices; LinkedList *exitPath, *tmp; scanf("%d", &vertexCount); allVertices = new Vertex[vertexCount]; for (n=0; nv->num, tmp->v->label*2, tmp->label); if ((tmp->v->label)*2 < tmp->label) { printf("Snark eats\n"); return 0; } tmp = tmp->next; } printf("Borogove escapes\n"); return 0; } LinkedList* FindShortestPath(Vertex *src, Vertex *dst) { // returns all the vertices in the shortest path, not necessarily in any order LinkedList *toVisit = NULL, *current, *tmp, *shortestPath = NULL; Vertex *v; src->label = 0; src->parent = NULL; if (src == dst) return NULL; tmp = src->edges; while (tmp != NULL) { Insert(tmp->v, &toVisit, tmp->label); // edges are labeled by their weight tmp->v->parent = src; tmp->v->label = tmp->label; tmp = tmp->next; } current = toVisit; toVisit = toVisit->next; while (current->v != dst) { tmp = current->v->edges; while (tmp != NULL) { // fprintf(stderr, "%d:%d=>%d(%d+%d) ", current->v->num, current->v->label, tmp->v->num, tmp->label, tmp->v->label); if ((tmp->v->label > current->v->label+tmp->label) || (tmp->v->label == current->v->label+tmp->label && ComparePaths(current->v, tmp->v->parent))) { tmp->v->parent = current->v; // set the vertex's parent to current vertex tmp->v->label = current->v->label+tmp->label; // mark the distance of the vertex Insert(tmp->v, &toVisit, current->v->label+tmp->label); // add that vertex to list } tmp = tmp->next; } delete current; // throw away the link current = toVisit; toVisit = toVisit->next; } v = dst; while (v != NULL) { Insert(v, &shortestPath, v->label); // labeled with borogove distances v = v->parent; } tmp = toVisit; while (tmp != NULL) { current = tmp; // free the rest of the toVisit list tmp = tmp->next; delete current; } // fprintf(stderr, "Done\n"); return shortestPath; } void MarkDistances(Vertex *src) { // marks shortest distance from src to every other reachable vertex LinkedList *toVisit = NULL, *current, *tmp; src->label = 0; tmp = src->edges; while (tmp != NULL) { Insert(tmp->v, &toVisit, tmp->label); // edges are labeled by their weight tmp->v->label = tmp->label; tmp = tmp->next; } current = toVisit; while (current != NULL) { tmp = current->v->edges; while (tmp != NULL) { if (tmp->v->label > current->v->label+tmp->label) { tmp->v->label = current->v->label+tmp->label; // mark the distance of the vertex Insert(tmp->v, &toVisit, current->v->label+tmp->label); // add that vertex to list } tmp = tmp->next; } delete current; // throw away the link toVisit = toVisit->next; current = toVisit; } } void Insert(Vertex *v, LinkedList **ll, int label) { // inserts vertex into ll, maintaining sort by label in ascending order LinkedList *tmp; if (*ll == NULL) { *ll = new LinkedList; (*ll)->v = v; (*ll)->next = NULL; (*ll)->label = label; } else if (label < (*ll)->label || ((label == (*ll)->label) && (v->num < (*ll)->v->num))) { tmp = new LinkedList; // the second and third clauses in the if ensure that if labels are tmp->v = v; // identical, the list will be sorted by the vertex number, in ascending order tmp->label = label; tmp->next = *ll; *ll = tmp; } else if ((*ll)->next == NULL) { (*ll)->next = new LinkedList; (*ll)->next->v = v; (*ll)->next->next = NULL; (*ll)->next->label = label; } else { Insert(v, &((*ll)->next), label); } } bool ComparePaths(Vertex *v1, Vertex *v2) { // this function is supposed to find the first room where the paths (specified by vertex->parent) // separate and return 1 if path1 has a lower room number, 0 otherwise int *vertices = new int[vertexCount]; int n; int path1diff = 0, path2diff = 0; Vertex *tmp; for (n=0; nnum] |= 1; tmp = tmp->parent; } tmp = v2; while (tmp != NULL) { vertices[tmp->num] |= 2; tmp = tmp->parent; } tmp = v1; while (tmp != NULL) { if (vertices[tmp->parent->num] == 3) { path1diff = tmp->num; break; } tmp = tmp->parent; } tmp = v2; while (tmp != NULL) { if (vertices[tmp->parent->num] == 3) { path2diff = tmp->num; break; } tmp = tmp->parent; } return path1diff