Skip to content

Instantly share code, notes, and snippets.

@pirapira
Created September 5, 2009 15:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pirapira/181437 to your computer and use it in GitHub Desktop.
Save pirapira/181437 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
enum dir {North, West, East, South, NONE};
unsigned int look_alt(int h, int w, int H, int W, enum dir dir, unsigned int *alt_map) {
#define ALT(m,n) *(alt_map + (m) * W + (n))
if (dir == North) {
if (h == 0)
return UINT_MAX;
else
return ALT(h - 1, w);
}
if (dir == West) {
if (w == 0)
return UINT_MAX;
else
return ALT(h, w - 1);
}
if (dir == East) {
if (w + 1 >= W)
return UINT_MAX;
else
return ALT(h, w + 1);
}
if (dir == South) {
if(h + 1 >= H)
return UINT_MAX;
else
return ALT(h+1, w);
}
}
enum dir water (int h, int w, int H, int W, unsigned int * alt_map) {
unsigned int min_alt = *(alt_map + h * W + w);
unsigned int cand_alt;
enum dir min_dir = NONE;
enum dir cand_dir;
cand_dir = North;
if ((cand_alt = look_alt(h, w, H, W, cand_dir, alt_map)) < min_alt) {
min_alt = cand_alt;
min_dir = cand_dir;
}
cand_dir = West;
if ((cand_alt = look_alt(h, w, H, W, cand_dir, alt_map)) < min_alt) {
min_alt = cand_alt;
min_dir = cand_dir;
}
cand_dir = East;
if ((cand_alt = look_alt(h, w, H, W, cand_dir, alt_map)) < min_alt) {
min_alt = cand_alt;
min_dir = cand_dir;
}
cand_dir = South;
if ((cand_alt = look_alt(h, w, H, W, cand_dir, alt_map)) < min_alt) {
min_alt = cand_alt;
min_dir = cand_dir;
}
return min_dir;
}
char follow(int h, int w, int H, int W,
unsigned int *alt_map, char* result_map, char* next_letter)
{
enum dir next = water(h, w, H, W, alt_map);
char ret;
char* result = result_map + h * W + w;
if (*result)
return *result;
switch(next) {
case NONE:
/* is basin */
*result = *next_letter;
(*next_letter) ++;
return *result;
case North:
ret = follow(h - 1, w, H, W, alt_map, result_map, next_letter);
break;
case West:
ret = follow(h, w - 1, H, W, alt_map, result_map, next_letter);
break;
case East:
ret = follow(h, w + 1, H, W, alt_map, result_map, next_letter);
break;
case South:
break;
}
*result = ret;
return ret;
}
void main(void) {
int T;
int t;
scanf("%d\n", &T);
for (t = 0; t < T; t++) {
int H, W;
int h, w;
unsigned int * alt_map;
char next_letter;
char * result_map;
next_letter = 'a';
scanf("%d %d\n", &H, &W);
alt_map = calloc(sizeof(unsigned int), H * W);
result_map = calloc(sizeof(char), H * W);
for (h = 0; h < H; h++) {
for (w = 0; w < W; w++)
scanf("%d ", alt_map + h * W + w);
}
for (h = 0; h < H; h++) {
for (w = 0; w < W; w++) {
follow(h, w, H, W, alt_map, result_map, &next_letter);
}
}
free(alt_map);
printf("Case #%d:\n", t + 1);
for (h = 0; h < H; h++) {
for (w = 0; w < W; w++) {
printf("%c", *(result_map + h * W + w));
if (w + 1 == W)
printf("\n");
else
printf(" ");
}
}
free(result_map);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment