阿里实习生笔试2018编程题之八阵图

5月11号晚上7点开始的阿里笔试,当时有点着急没写出来,现在把代码码出来,题目没有记录下来,以后再补充。

输入第一行是矩阵的行数
第二行是矩阵的列数
后面则是矩阵内容

输入范例:
20
20
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

输出范例:
323
116

思路是用递归生成一个mask,根据mask来对8块兵阵进行加和计算

python代码如下:

# 开始查找兵阵的坐标,分别从八个位置查找八个兵阵
start_idx = {'top_left': (0, 0), 'top_mid': (0, cols//2), 'top_right': (0, cols-1),
             'mid_left': (rows//2, 0), 'mid_right': (rows//2, cols-1),
             'bot_left': (rows-1, 0), 'bot_mid': (rows-1, cols//2), 'bot_right': (rows-1, cols-1)}


class Graph(object):
    def __init__(self, row, col, g):
    # row是行数,col是列数,g是输入的八阵图
        self.row = row
        self.col = col
        self.g = g
        self.mask = [[0 for _ in range(self.col)] for _ in range(self.row)]
        self.mask_idx = 1
        self.iter = 0
        self.sum_list = [0 for _ in range(8)]

    def is_soldier(self, x, y):
    # 判断该点是否为兵阵
        if self.g[x][y] > 0:
            return True
        else:
            return False

    def surround(self, ix, iy):
    # 返回点(ix,iy)周围的坐标
        xy = []
        if ix-1 >= 0 and iy-1 >= 0:
            xy.append((ix-1, iy-1))
        if ix >= 0 and iy-1 >= 0:
            xy.append((ix, iy-1))
        if ix-1 >= 0 and iy >= 0:
            xy.append((ix-1, iy))
        if ix-1 >= 0 and iy+1 < cols:
            xy.append((ix-1, iy+1))
        if ix >= 0 and iy+1 < cols:
            xy.append((ix, iy+1))
        if ix+1 < rows and iy-1 >= 0:
            xy.append((ix+1, iy-1))
        if ix+1 < rows and iy >= 0:
            xy.append((ix+1, iy))
        if ix+1 < rows and iy+1 < cols:
            xy.append((ix+1, iy+1))
        return xy

    def mask_gen(self, ix, iy):
    # 生成mask,递归
        sur = self.surround(ix, iy)
        valid_xy = []
        should_stop = True
        if self.is_soldier(ix, iy) and self.mask[ix][iy] == 0:
            self.mask[ix][iy] = self.mask_idx
        for x, y in sur:
            if self.is_soldier(x, y) and self.mask[x][y] == 0:
                should_stop = False
                valid_xy.append((x, y))
                self.iter += 1
        if should_stop is True:
            return None

        for x, y in valid_xy:
            self.mask_gen(x, y)

    def reset_search(self):
    # self.iter是用来判断初始点是否找到兵阵
        self.iter = 0

    def search(self, mode):
        start_x, start_y = start_idx[mode]
        while self.iter == 0:
            self.mask_gen(start_x, start_y)
            if self.iter == 0:
            # 如果初始点没找到兵阵,根据mode决定初始点继续搜索的方向
                if 'top' in mode:
                    start_y += 1
                elif 'bot' in mode:
                    start_y -= 1
                if 'left' in mode:
                    start_x += 1
                elif 'right' in mode:
                    start_x -= 1
        # 找到一个完整的兵阵就把mask的值加一
        self.mask_idx += 1

    def search_all(self):
    # 搜索八个方向
        for mode in start_idx.keys():
            self.search(mode)
            self.reset_search()

    def sum_up(self):
    # 把八个兵阵的值累加起来
        for x in range(self.row):
            for y in range(self.col):
                if self.mask[x][y] > 0:
                    self.sum_list[self.mask[x][y]-1] += self.g[x][y]


gg = Graph(rows, cols, g)
gg.search_all()
gg.sum_up()
print(max(gg.sum_list))
print(min(gg.sum_list))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值