【华为OD】2024D卷——围棋的气

题目描述:

围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19x19=361个交点,对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。
“气”是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子,由此可知:

1、在棋盘的边缘上的棋子最多有3口气(黑1),在棋盘角点的棋子最多有2口气(黑2),其它情况最多有4口气(白1)
2、所有同色棋子的气之和叫作该色棋子的气,需要注意的是,同色棋子重合的气点,对于该颜色棋子来说,只能计算一次气,
比如下图中,黑棋一共4口气,而不是5口气,因为黑1和黑2中间红色三角标出的气是两个黑棋共有的,对于黑棋整体来说只能算一个气。
3、本题目只计算气,对于眼也按气计算,如果您不清楚“眼”的概念,可忽略,按照前面描述的规则计算即可。
现在,请根据输入的黑棋和白棋的坐标位置,计算黑棋和白棋一共各有多少气?

输入描述:
输入包括两行数据,如:
0 5 8 9 9 10
5 0 9 9 9 8
说明:
1、每行数据以空格分隔,数据个数是2的整数倍,每两个数是一组,代表棋子在棋盘上的坐标;
2、坐标的原点在棋盘左上角点,第一个值是行号,范围从0到18;第二个值是列号,范围从0到18。
输出:
8 7
说明:
黑棋有8口“气”,白棋有7口“气”

解题思路:

1、初始化棋盘:使用一个19x19的二维数组来表示棋盘,其中0表示空位,1表示黑棋,2表示白棋。

2、将输入数据填入棋盘:将输入的黑棋和白棋的坐标填入棋盘,需单读处理白棋和黑棋的输入和气数。

3、计算气数:使用DFS遍历棋盘上的每一个位置,并计算每个棋子的气数:

     ·如果该位置没有棋子(即值为0),则检查其上下左右四个方向是否有棋子(黑棋或白棋)

     ·如果有,则根据棋子的颜色(黑棋或白棋)增加对应颜色的“气”的数量

     ·需要注意的是,同色棋子重合的气点只能计算一次

4、输出黑棋和白棋的总气数


代码部分

#检查坐标(x,y)是否在棋盘范围内,防止DFS检查坐标越界
def in_bounds(x, y):
    return 0 <= x <= 18 and 0 <= y <= 18

#使用DFS计算棋的气数
def dfs(board, x, y, color, visited):
    stack = [(x, y)]        #stack用于保存需要检查的棋子的坐标
    # visited[x][y] = True        #visited数组用于记录是否已经访问过该位置
    qi = 0
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    while stack:
        c_x, c_y = stack.pop()
        #依次访问棋子的四个方位:左、右、下、上
        for d_x, d_y in directions:
            n_x, n_y = c_x + d_x, c_y + d_y
            if in_bounds(n_x, n_y):     #确认四个方向坐标位于棋盘中
                if board[n_x][n_y] == 0 and not visited[n_x][n_y]:        #此坐标没有棋子
                    visited[n_x][n_y] = True    #此坐标已经访问,算入气中,确保同色棋子重合的气点只能计算一次
                    qi += 1
                elif board[n_x][n_y] == color and not visited[n_x][n_y]:        #此坐标有相同颜色棋子,但未曾被访问,压入栈中
                    visited[n_x][n_y] = True
                    stack.append((n_x, n_y))        #保证算法能够完整地探索所有与初始棋子相连的同色棋子

                #else:此坐标存在另一种颜色棋子,不做任何操作
    return qi

#计算指定颜色棋子的总气数
def calculate_qi(board, color):
    visited = [[False for _ in range(19)] for _ in range(19)]
    total_qi = 0
    for i in range(19):
        for j in range(19):
            if board[i][j] == color and not visited[i][j]:      #计算未访问过的对应color棋子的气
                visited[i][j] = True
                #将(i,j)处棋子访问标志置为1,这样dfs函数可省略visited[x][y] = True;
                # 若不写,需要在dfs函数中将棋子访问标志置1
                total_qi += dfs(board, i, j, color, visited)
    return total_qi

def main():
    #初始化棋盘
    board = [[0 for _ in range(19)] for _ in range(19)]

    """
    #直接输入棋盘的情况
    board = []
    for _ in range(19):
        line = input().strip()
        board.append([int(char) for char in line])
    """
    #读取黑棋坐标
    black_positions = list(map(int, input().split()))
    for i in range(0, len(black_positions), 2):
        x, y = black_positions[i], black_positions[i + 1]
        board[x][y] = 1
    #读取白棋坐标
    white_positions = list(map(int,input().split()))
    for i in range(0, len(white_positions), 2):
        x, y = white_positions[i], white_positions[i + 1]
        board[x][y] = 2
    #计算黑白棋总气数
    black_qi = calculate_qi(board, 1)
    white_qi = calculate_qi(board, 2)

    print(black_qi, white_qi)

if __name__ =='__main__':
    main()

知识点:图、DFS、列表


结语:越简单的题目解法应该越多,请路过大神留下新的思路供本小白学习一下,打开思路

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值