• google code jam exercise——Water Sheds


    Water Sheds,这是Qualification Round 2009的第二道题,还没有想到好的解决办法的时候,直接看了参考解答。参考解答研究了好久才看明白,看来还需要加强练习。

    先来看看题目意思,给定一个mxn的矩阵,每个位置是一个海拔值,相当于是一份地图,要求根据水流给这份地图进行标注,水流动的规则是,

    1. 对任一个位置,至多流向它的四个邻居中的一个,邻居就是东南西北方向的四个位置;

    2. 如果相比于四个邻居,它本身的海拔最低,那么水不流动,这个位置称为sink,盆地;

    3. 否则,水流向海拔最低的一个邻居;

    4. 选择海拔最低的邻居的顺序是,North,West,East,South,即北,西,东,南。

    解题步骤如下:

    0. 初始化当前label="a"

    1. 遍历地图中所有位置,对任一位置(ui,uj),寻找它所在的盆地;

    2. 寻找盆地的方法,以(i,j)=(ui,uj)为起始点,找四个邻居中最小的一个,如果没有比它更小的,即找到了相应的盆地(i,j);

    3. 如果四个邻居中有更小的(nexti,nextj),那么继续以(i,j)=(nexti,nextj)为起始点寻找盆地。

    4. 找到相应的盆地(i,j)之后,查看(i,j)位置是否已经标注,如果没有,则将其标注为当前label,并且,label=label+1;

    5. (ui,uj)即得到与(i,j)相同的标注

    代码如下:

    #/usr/bin/python
    #
    encoding:UTF-8
    #
    Filename:WaterSheds_Ref.py

    import sys

    def ReadInts():
    return list(map(int, sys.stdin.readline().strip().split(" ")))

    def Cross(a, b):
    for i in a:
    for j in b:
    yield (i, j)

    def Neighbours(ui, uj, m, n):
    if ui - 1 >= 0: yield (ui - 1, uj)
    if uj - 1 >= 0: yield (ui, uj - 1)
    if uj + 1 < n: yield (ui, uj + 1)
    if ui + 1 < m: yield (ui + 1, uj)

    fin = open(sys.argv[1])
    sys.stdin = fin

    fout = open(sys.argv[1].replace(".in",".out"),"w")

    N = ReadInts()[0]
    for prob in xrange(1, N + 1):
    # Read the map
    (m, n) = ReadInts()
    maze = [ReadInts() for _ in xrange(m)]
    answer = [["" for _ in xrange(n)] for _ in xrange(m)]
    # The map from sinks to labels.
    label = {}
    next_label = 'a'
    # Brute force each cell.
    for (ui, uj) in Cross(xrange(m), xrange(n)):
    (i, j) = (-1, -1)
    (nexti, nextj) = (ui, uj)
    while (i, j) != (nexti, nextj):
    (i, j) = (nexti, nextj)
    for (vi, vj) in Neighbours(i, j, m, n):
    if maze[vi][vj] < maze[nexti][nextj]:
    (nexti, nextj) = (vi, vj)

    # Cell (ui, uj) drains to (i, j).
    if (i, j) not in label:
    label[(i, j)] = next_label
    next_label = chr(ord(next_label) + 1)
    answer[ui][uj] = label[(i, j)]

    # Output the labels.
    #
    print "Case #%d:" % prob
    an = "Case #%d:\n" % prob
    for i in xrange(m):
    # print " ".join(answer[i])
    an = an + " ".join(answer[i])
    an = an + "\n"
    fout.write(an)

    fin.close()
    fout.close()

    关于代码的几点解释:
    1. sys.stdin=fin

    在Contest Analysis给出的参考程序中,ReadInts直接从stdin读取数据,而我一般习惯从文件读取测试数据,所以使用了重定向,在C/C++里面是可以这样用的,所以试了一下,发现这里也可以这样用。

    2. ReadInts

    这是读取输入数据的函数,一句话就解决了,之前我都是先line=fin.readline(),然后去掉line最后的"\n",然后使用split分割,最后将字符串转换成int,很多条语句,这里一行就搞定了。这种写法很好玩的。

    3. yield

    这是一种更好玩的写法。虽然是把这里的程序看懂了,但如何使用yield还是不熟悉,以后可以多练习。

    一切愉快!

  • 相关阅读:
    kubeadm部署kubernetes
    一键部署redis-5.0.5
    二进制部署kubernetes高可用
    设计模式--行为型模式--观察者模式(Observer模式)
    设计模式--行为型模式--状态模式
    设计模式--行为型模式--责任链模式(职责链模式)
    《数学之美》在线阅读
    设计模式--行为型模式--命令模式
    设计模式--行为型模式--策略模式
    设计模式--行为型模式--模板方法模式
  • 原文地址:https://www.cnblogs.com/Frandy/p/google_code_jam_water_sheds_python.html
Copyright © 2020-2023  润新知