checkio (Digging a canal)

The robots are trying to colonize a new island. There are many rivers on this island and it would be good idea for them to use ships designed for water, rather than their spaceships. Some of the territories do not have a river for transportation from one edge of a field to another. The robots can dig a canal and convert the land to water if need be. We must explore a field map and count the minimum number of cells necessary for a canal that would allow the robots to sail from northern edge of the map to southern edge. The map is in a 2D array, where 0 is water, 1 is land. Cells are connected by their edges.

Input: A list of lists with 1 or 0.

Output: The minimum number of cells necessary for a canal. An integer.

Example:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
checkio([[1, 1, 1, 1, 0, 1, 1],
         [1, 1, 1, 1, 0, 0, 1],
         [1, 1, 1, 1, 1, 0, 1],
         [1, 1, 0, 1, 1, 0, 1],
         [1, 1, 0, 1, 1, 1, 1],
         [1, 0, 0, 1, 1, 1, 1],
         [1, 0, 1, 1, 1, 1, 1]]) == 2
checkio([[0, 0, 0, 0, 0, 0, 0],
         [1, 1, 1, 1, 1, 1, 1],
         [1, 1, 1, 1, 1, 1, 1],
         [1, 1, 1, 1, 1, 1, 1],
         [1, 1, 0, 1, 0, 1, 1],
         [1, 0, 0, 0, 0, 0, 1],
         [0, 0, 0, 0, 0, 0, 0]]) == 3
checkio([[1, 1, 1, 1, 1, 0, 1, 1],
         [1, 0, 1, 1, 1, 0, 1, 1],
         [1, 0, 1, 0, 1, 0, 1, 0],
         [1, 0, 1, 1, 1, 0, 1, 1],
         [0, 0, 1, 1, 0, 0, 0, 0],
         [1, 0, 1, 1, 1, 1, 1, 1],
         [1, 0, 1, 1, 1, 1, 1, 1],
         [1, 1, 1, 0, 1, 1, 1, 1]]) == 2

How it is used: Optimization software.

优先队列+广搜,说白了其实是dijkstra,只不过不用记录那么多距离信息。

import heapq
cx = [-1,0,1,0]
cy = [0,1,0,-1]

def checkio(data):
    priority_queue = []
    heapq.heapify(priority_queue)
    rown = len(data)
    coln = len(data[0])
    visit = set()
    for i in range(coln):
        if data[0][i] == 1:
            heapq.heappush(priority_queue, (1, 0, i))
        else:
            heapq.heappush(priority_queue, (0, 0, i))
        visit.add((0, i))

    while priority_queue:
        step, x, y = heapq.heappop(priority_queue)
        #print x, y, step
        if x == rown-1:
            return step
        for i in range(4):
            tx = x + cx[i]
            ty = y + cy[i]
            if tx >= 0 and tx < rown and ty >= 0 and ty < coln:
                if (tx, ty) not in visit:
                    if data[tx][ty] == 1:
                        heapq.heappush(priority_queue, (step+1, tx, ty))
                    else:
                        heapq.heappush(priority_queue, (step, tx, ty))
                    visit.add((tx, ty))

#These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
    assert checkio([[1, 1, 1, 1, 0, 1, 1],
                    [1, 1, 1, 1, 0, 0, 1],
                    [1, 1, 1, 1, 1, 0, 1],
                    [1, 1, 0, 1, 1, 0, 1],
                    [1, 1, 0, 1, 1, 1, 1],
                    [1, 0, 0, 1, 1, 1, 1],
                    [1, 0, 1, 1, 1, 1, 1]]) == 2, "1st example"
    assert checkio([[0, 0, 0, 0, 0, 0, 0],
                    [1, 1, 1, 1, 1, 1, 1],
                    [1, 1, 1, 1, 1, 1, 1],
                    [1, 1, 1, 1, 1, 1, 1],
                    [1, 1, 0, 1, 0, 1, 1],
                    [1, 0, 0, 0, 0, 0, 1],
                    [0, 0, 0, 0, 0, 0, 0]]) == 3, "2nd example"
    assert checkio([[1, 1, 1, 1, 1, 0, 1, 1],
                    [1, 0, 1, 1, 1, 0, 1, 1],
                    [1, 0, 1, 0, 1, 0, 1, 0],
                    [1, 0, 1, 1, 1, 0, 1, 1],
                    [0, 0, 1, 1, 0, 0, 0, 0],
                    [1, 0, 1, 1, 1, 1, 1, 1],
                    [1, 0, 1, 1, 1, 1, 1, 1],
                    [1, 1, 1, 0, 1, 1, 1, 1]]) == 2, "3rd example"


你可能感兴趣的:(checkio (Digging a canal))