Submission #160323

#TimeUsernameProblemLanguageResultExecution timeMemory
160323model_codeClimbers (RMI18_climbers)C11
100 / 100
229 ms59256 KiB
/** * Method: treat pairs of altitudes as vertices in a graph, then run * Dijkstra's algorithm. * * Author: Catalin Francu * * Implementation details: we insert vertices into the heap lazily when they * are first reached. This reduces the heap size dramatically and speeds up * the program by a factor of 2 or 3. * * In order to run decreaseKey() when reaching a vertex that's already in the * heap, we store the heap index of each vertex in hp[]. **/ #include <stdio.h> #include <stdlib.h> #define MAX_N 5000 /* heap positions */ #define NEW 0 /* node not yet inserted */ #define REMOVED -1 /* node was processed and removed */ typedef unsigned long long u64; typedef struct { short x, y; u64 dist; } node; int n; int heapSize; int alt[MAX_N + 1]; int hp[MAX_N][MAX_N]; node h[MAX_N * MAX_N + 1]; /* heap is 1-based */ /* returns true if the altitudes at i, j and k are in ascending or descending order */ int sequence(int i, int j, int k) { return (alt[i] <= alt[j] && alt[j] <= alt[k]) || (alt[i] >= alt[j] && alt[j] >= alt[k]); } void heapMove(int from, int to) { hp[h[from].x][h[from].y] = to; h[to] = h[from]; } void heapSiftUp(int pos) { node n = h[pos]; while ((pos > 1) && (n.dist < h[pos / 2].dist)) { heapMove(pos / 2, pos); pos /= 2; } hp[n.x][n.y] = pos; h[pos] = n; } void heapSiftDown() { int pos = 1; node n = h[pos]; int done = 0; while (!done) { int child = pos; if ((2 * pos <= heapSize) && (h[2 * pos].dist < h[child].dist)) { child = 2 * pos; } if ((2 * pos + 1 <= heapSize) && (h[2 * pos + 1].dist < h[child].dist)) { child = 2 * pos + 1; } if (child != pos) { heapMove(child, pos); h[child] = n; pos = child; } else { done = 1; } } hp[n.x][n.y] = pos; } void heapRemoveMin(int* x, int* y, u64* dist) { *x = h[1].x; *y = h[1].y; *dist = h[1].dist; heapMove(heapSize--, 1); heapSiftDown(); hp[*x][*y] = REMOVED; } void decreaseKey(int x, int y, u64 dist) { if (x < 0 || x >= n || y < 0 || y >= n) { return; /* range checking */ } int pos = hp[x][y]; switch (pos) { case REMOVED: /* nothing -- node was already processed */ break; case NEW: /* add the node to the heap */ hp[x][y] = ++heapSize; h[heapSize] = (node) { x, y, dist }; heapSiftUp(heapSize); break; default: if (dist < h[pos].dist) { /* existing node and smaller distance */ h[pos].dist = dist; heapSiftUp(pos); } } } u64 dijkstra() { int x = 0, y = n - 1; u64 d = 0; while (x != y) { /* loop invariant: alt[y], alt[x] and alt[y + 1] are sorted */ /* corner cases */ if (alt[x] == alt[y]) { decreaseKey(x, y - 1, d); decreaseKey(y, x, d); decreaseKey(y, x - 1, d); } if (alt[x] == alt[y + 1]) { decreaseKey(x, y, d); decreaseKey(y + 1, x, d); decreaseKey(y + 1, x - 1, d); } /* go towards x + 1 */ if (x + 1 < n) { if (sequence(y, x + 1, y + 1)) { decreaseKey(x + 1, y, d + abs(alt[x] - alt[x + 1])); } else if (sequence(x + 1, y, x)) { decreaseKey(y, x, d + abs(alt[x] - alt[y])); } else { decreaseKey(y + 1, x, d + abs(alt[x] - alt[y + 1])); } } /* go towards x - 1 */ if (x > 0) { if (sequence(y, x - 1, y + 1)) { decreaseKey(x - 1, y, d + abs(alt[x] - alt[x - 1])); } else if (sequence(x - 1, y, x)) { decreaseKey(y, x - 1, d + abs(alt[x] - alt[y])); } else { decreaseKey(y + 1, x - 1, d + abs(alt[x] - alt[y + 1])); } } heapRemoveMin(&x, &y, &d); } return d; } int main() { int numAlts; /* read altitudes, suppressing repeated values and monotonic runs */ scanf("%d%d%d", &numAlts, &alt[0], &alt[1]); n = 2; while (numAlts-- > 2) { scanf("%d", &alt[n]); if (sequence(n - 2, n - 1, n)) { alt[n - 1] = alt[n]; } else { n++; } } u64 answer = dijkstra(); printf("%llu\n", answer); }

Compilation message (stderr)

climbers.c: In function 'main':
climbers.c:174:3: warning: ignoring return value of 'scanf', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%d%d", &numAlts, &alt[0], &alt[1]);
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
climbers.c:177:5: warning: ignoring return value of 'scanf', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &alt[n]);
     ^~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...