Google Code Jam 2009 Qualification Round Problem B. Watersheds

https://code.google.com/codejam/contest/90101/dashboard#s=p1

 

Problem

Geologists sometimes divide an area of land into different regions based on where rainfall flows down to. These regions are called drainage basins.

Given an elevation map (a 2-dimensional array of altitudes), label the map such that locations in the same drainage basin have the same label, subject to the following rules.

  • From each cell, water flows down to at most one of its 4 neighboring cells.
  • For each cell, if none of its 4 neighboring cells has a lower altitude than the current cell's, then the water does not flow, and the current cell is called a sink.
  • Otherwise, water flows from the current cell to the neighbor with the lowest altitude.
  • In case of a tie, water will choose the first direction with the lowest altitude from this list: North, West, East, South.

Every cell that drains directly or indirectly to the same sink is part of the same drainage basin. Each basin is labeled by a unique lower-case letter, in such a way that, when the rows of the map are concatenated from top to bottom, the resulting string is lexicographically smallest. (In particular, the basin of the most North-Western cell is always labeled 'a'.)

 

Input

The first line of the input file will contain the number of maps, TT maps will follow, each starting with two integers on a line -- H and W -- the height and width of the map, in cells. The next H lines will each contain a row of the map, from north to south, each containingW integers, from west to east, specifying the altitudes of the cells.

Output

For each test case, output 1+H lines. The first line must be of the form

Case #X:

where X is the test case number, starting from 1. The next H lines must list the basin labels for each of the cells, in the same order as they appear in the input.

 

Limits

T ≤ 100;

Small dataset

1 ≤ HW ≤ 10;
0 ≤ altitudes < 10.
There will be at most two basins.

Large dataset

1 ≤ HW ≤ 100;
0 ≤ altitudes < 10,000.
There will be at most 26 basins.

Sample


Input 
 

Output 
 
5
3 3
9 6 3
5 9 6
3 5 9
1 10
0 1 2 3 4 5 6 7 8 7
2 3
7 6 7
7 6 7
5 5
1 2 3 4 5
2 9 3 9 6
3 3 0 8 7
4 9 8 9 8
5 6 7 8 9
2 13
8 8 8 8 8 8 8 8 8 8 8 8 8
8 8 8 8 8 8 8 8 8 8 8 8 8
Case #1:
a b b
a a b
a a a
Case #2:
a a a a a a a a a b
Case #3:
a a a
b b b
Case #4:
a a a a a
a a b b a
a b b b a
a b b b a
a a a a a
Case #5:
a b c d e f g h i j k l m
n o p q r s t u v w x y z

Notes

In Case #1, the upper-right and lower-left corners are sinks. Water from the diagonal flows towards the lower-left because of the lower altitude (5 versus 6).

 

Solution:

int H, W;
vector<vector<int>>mmap;

pair<int, int> r_cell (int X, int Y)
{
    int alt = mmap[X][Y];
    int min_alt = alt;
    int tX, tY, maX = -1, maY = -1;
    
    tX = X - 1; tY = Y - 0;
    if (tX >= 0 && tX < H && tY >= 0 && tY < W)
        if (mmap[tX][tY] < min_alt) {
            min_alt = mmap[tX][tY];
            maX = tX; maY = tY;
        }

    tX = X - 0; tY = Y - 1;
    if (tX >= 0 && tX < H && tY >= 0 && tY < W)
        if (mmap[tX][tY] < min_alt) {
            min_alt = mmap[tX][tY];
            maX = tX; maY = tY;
        }
    
    tX = X - 0; tY = Y + 1;
    if (tX >= 0 && tX < H && tY >= 0 && tY < W)
        if (mmap[tX][tY] < min_alt) {
            min_alt = mmap[tX][tY];
            maX = tX; maY = tY;
        }
    
    tX = X + 1; tY = Y - 0;
    if (tX >= 0 && tX < H && tY >= 0 && tY < W)
        if (mmap[tX][tY] < min_alt) {
            min_alt = mmap[tX][tY];
            maX = tX; maY = tY;
        }
    
    if ((min_alt) < alt) {
        return r_cell(maX, maY);
    } else {
        return pair<int, int>(X, Y);
    }

}

map<pair<int, int>, char> solve()
{
    
    map<pair<int, int>, vector<pair<int, int>>>sinks;
    map<pair<int, int>, char>sinklabel;
    map<pair<int, int>, char>label;
    char b_label = 'a' - 1;
    
    for (int h = 0; h < H; h++) {
        for (int w = 0; w < W; w++) {
            pair<int, int> cell = r_cell(h, w);

            if (!sinks.count(pair<int, int>(cell.first, cell.second))) {
                b_label++;
                
                // new sink
                sinks.insert(pair<pair<int, int>, vector<pair<int, int>>>(pair<int, int>(cell.first, cell.second), vector<pair<int, int>>()));
                sinklabel.insert(pair<pair<int, int>, char>(pair<int, int>(cell.first, cell.second), b_label));
            }
            
            // add to existing sink
            sinks.at(pair<int, int>(cell.first, cell.second)).push_back(pair<int, int>(h, w));
            label.insert(pair<pair<int, int>, char>(pair<int, int>(h, w), sinklabel.at(pair<int, int>(cell.first, cell.second))));
        }
    }
    
    return label;
}

int main()
{

    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
    
    int T;
    scanf("%d\n", &T);
    if (!T) {
        cerr << "Check input!" << endl;
        exit(0);
    }
    
    for (int t = 1; t <= T; t++) {
        scanf("%d %d\n", &H, &W);
        
        // map
        mmap.clear();
        int alt;
        for (int h = 0; h < H; h++) {
            vector<int> row;
            for (int w = 0; w < W; w++) {
                scanf("%d", &alt);
                row.push_back(alt);
            }
            mmap.push_back(row);
        }
        
        auto result = solve();
        printf("Case #%d:\n", t);
        
        for (int h = 0; h < H; h++) {
            for (int w = 0; w < W; w++) {
                printf("%c ", result.at(pair<int, int>(h, w)));
            }
            printf("\n");
        }
    }
    
    fclose(stdin);
    fclose(stdout);
    return 0;
}

 

 

posted @ 2014-04-21 17:36  Yunzhu  阅读(296)  评论(0编辑  收藏  举报