阿里面试题 八阵图问题 思路详解 (python 实现)/ 阿里实习生笔试2018编程题之八阵图

版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载,加上原文链接即可~~ https://blog.csdn.net/hpulfc/article/details/81486447

题目:

八卦阵相传是诸葛亮创设的一种战斗队形和兵力部署,由八种阵势组成。为了方便,采用矩阵描述一个八卦阵,它由八个单阵组成,,每个单阵由多个兵力区域组成一种阵势,如图所示,其中数字为一个兵力区域的士兵个数。假设单阵与单阵之间兵力区域不会相邻,且单阵中兵力区域至少存在一个兵力相邻区域(注:相邻是指再其↖、正上、↗、正右、↘、正下、↙、正左八个方位与其相邻),请用最快的速度计算出八个单阵中的兵力(士兵个数)的最大值和最小值。

输入:

一个二维矩阵,对应着的是元素的值是行和列的大小 以及每个点的士兵的个数。

思路:

根据题意,一个阵中八个单阵,要计算的是八个单阵中最大和最小值。一定要先简化,并明确问题。

那么只需要计算每个单阵的士兵数量即可。

这里有几个关键点:

  1. 单阵个数的统计
  2. 单阵士兵的计算

重点:构造合适的数据结构

详细解释:

对于上下左右分别定义一些操作,模拟移动。

对于单阵,其实质就是一个多路的树,只不过有些分支不符合要求。模拟树的搜索即可找到一个单阵中所有的有效的点。

对于寻找所有的阵型,可以直接遍历一下,寻找即可,根据题意共有八个,所以只要找到八个属于单阵中的点,通过单阵中的点进行单阵搜索,题目的解!

代码:

# coding=utf8
__author__ = 'lfc'

from queue import Queue

# 定义操作,八个方向
op = {
    "u": lambda i, j: (i - 1, j),
    "u_r": lambda i, j: (i - 1, j + 1),
    "r": lambda i, j: (i, j + 1),
    "d_r": lambda i, j: (i + 1, j + 1),
    "d": lambda i, j: (i + 1, j),
    "d_l": lambda i, j: (i + 1, j - 1),
    "l": lambda i, j: (i, j - 1),
    "u_l": lambda i, j: (i - 1, j - 1),
}

# 八个阵型
graphs = {
    "0": set(),
    "1": set(),
    "2": set(),
    "3": set(),
    "4": set(),
    "5": set(),
    "6": set(),
    "7": set(),
}


# 检验点的合法性
def check(i, j, x, y, g_count, ri):
    if i < 0 or i >= x or j < 0 or j >= y:
        return False

    if (i, j) in graphs[str(g_count)]:
        return False

    print i, j
    if ri[i][j] == 0:
        return False

    return True


# 单个阵型的搜索
def single_search(i, j, x, y, g_count, ri):
    g_count = str(g_count)
    q = Queue(maxsize=x * y)
    q.put((i, j))

    while not q.empty():
        i, j = q.get()
        print "get", i, j
        for k, v in op.items():
            n_i, n_j = v(i, j)
            if check(n_i, n_j, x, y, g_count, ri):
                print "add", n_i, n_j
                q.put((n_i, n_j))
                graphs[g_count].add((n_i, n_j))  # 这个地方笔误写错成 n_j, n_j 注意

    all_count = 0
    for item_i, item_j in graphs[g_count]:
        all_count += ri[item_i][item_j]

    # print all_count, "-=" * 20
    return all_count


# 当前点是否属于新的阵型
def is_single_graph(i, j):
    for k, v in graphs.iteritems():
        if (i, j) in v:
            return False

    return True


# 搜索所有的点,找到所有阵型,并求出最大,最小值
def all_search(x, y, ri):
    g_count = 0
    max_v = -0xffffff
    min_v = 0xffffff
    for i in range(x):
        for j in range(y):
            if ri[i][j] > 0 and is_single_graph(i, j):
                current_count = single_search(i, j, x, y, g_count, ri)

                g_count += 1
                if current_count > max_v:
                    max_v = current_count

                if current_count < min_v:
                    min_v = current_count

    return max_v, min_v


# 测试数据
n = [[34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 30],
     [0, 23, 10, 5, 5, 0, 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 30, 0, 40, 0],
     [0, 9, 0, 0, 5, 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 30, 0, 0],
     [0, 8, 7, 7, 0, 5, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 7, 0, 9, 0],
     [0, 9, 0, 0, 5, 0, 5, 0, 0, 12, 12, 0, 0, 0, 0, 10, 0, 0, 0, 9],
     [0, 0, 0, 0, 5, 0, 0, 5, 0, 12, 12, 0, 0, 5, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 5, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0],
     [40, 30, 3, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 10, 0],
     [0, 0, 20, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 5, 6, 5, 10, 10, 0],
     [40, 30, 3, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 10, 0],
     [0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 17, 0, 0, 6, 5, 7, 7, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 20, 0, 0, 7, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0],
     [0, 20, 0, 0, 7, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0],
     [0, 20, 0, 0, 7, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 10, 0, 0, 0],
     [0, 30, 0, 7, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 10, 0, 50],
     [0, 40, 7, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 50, 0],
     [43, 30, 25, 10, 50, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 50, 0, 0]]

print all_search(20, 20, n)

输出:

(323, 116)  


另外,用python 写代码简洁,易懂!

猜你喜欢

转载自blog.csdn.net/hpulfc/article/details/81486447